vty.c 69 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148
  1. /*
  2. * Virtual terminal [aka TeletYpe] interface routine.
  3. * Copyright (C) 1997, 98 Kunihiro Ishiguro
  4. *
  5. * This file is part of GNU Zebra.
  6. *
  7. * GNU Zebra is free software; you can redistribute it and/or modify it
  8. * under the terms of the GNU General Public License as published by the
  9. * Free Software Foundation; either version 2, or (at your option) any
  10. * later version.
  11. *
  12. * GNU Zebra is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with GNU Zebra; see the file COPYING. If not, write to the Free
  19. * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  20. * 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "linklist.h"
  24. #include "thread.h"
  25. #include "buffer.h"
  26. #include <lib/version.h>
  27. #include "command.h"
  28. #include "sockunion.h"
  29. #include "memory.h"
  30. #include "str.h"
  31. #include "log.h"
  32. #include "prefix.h"
  33. #include "filter.h"
  34. #include "vty.h"
  35. #include "privs.h"
  36. #include "network.h"
  37. #include <arpa/telnet.h>
  38. #include <termios.h>
  39. #define VTY_BUFSIZ 4096
  40. /* Vty events */
  41. enum event
  42. {
  43. VTY_SERV,
  44. VTY_READ,
  45. VTY_WRITE,
  46. VTY_TIMEOUT_RESET,
  47. #ifdef VTYSH
  48. VTYSH_SERV,
  49. VTYSH_READ,
  50. VTYSH_WRITE
  51. #endif /* VTYSH */
  52. };
  53. static void vty_event (enum event, int, struct vty *);
  54. /* Extern host structure from command.c */
  55. extern struct host host;
  56. /* Vector which store each vty structure. */
  57. static vector vtyvec;
  58. /* Vty timeout value. */
  59. static unsigned long vty_timeout_val = VTY_TIMEOUT_DEFAULT;
  60. /* Vty access-class command */
  61. static char *vty_accesslist_name = NULL;
  62. /* Vty access-calss for IPv6. */
  63. static char *vty_ipv6_accesslist_name = NULL;
  64. /* VTY server thread. */
  65. static vector Vvty_serv_thread;
  66. /* Current directory. */
  67. char *vty_cwd = NULL;
  68. /* Configure lock. */
  69. static int vty_config;
  70. /* Login password check. */
  71. static int no_password_check = 0;
  72. /* Restrict unauthenticated logins? */
  73. static const u_char restricted_mode_default = 0;
  74. static u_char restricted_mode = 0;
  75. /* Integrated configuration file path */
  76. char integrate_default[] = SYSCONFDIR INTEGRATE_DEFAULT_CONFIG;
  77. static int do_log_commands = 0;
  78. /* VTY standard output function. */
  79. int
  80. vty_out (struct vty *vty, const char *format, ...)
  81. {
  82. va_list args;
  83. int len = 0;
  84. int size = 1024;
  85. char buf[1024];
  86. char *p = NULL;
  87. if (vty_shell (vty))
  88. {
  89. va_start (args, format);
  90. vprintf (format, args);
  91. va_end (args);
  92. }
  93. else
  94. {
  95. /* Try to write to initial buffer. */
  96. va_start (args, format);
  97. len = vsnprintf (buf, sizeof(buf), format, args);
  98. va_end (args);
  99. /* Initial buffer is not enough. */
  100. if (len < 0 || len >= size)
  101. {
  102. while (1)
  103. {
  104. if (len > -1)
  105. size = len + 1;
  106. else
  107. size = size * 2;
  108. p = XREALLOC (MTYPE_VTY_OUT_BUF, p, size);
  109. if (! p)
  110. return -1;
  111. va_start (args, format);
  112. len = vsnprintf (p, size, format, args);
  113. va_end (args);
  114. if (len > -1 && len < size)
  115. break;
  116. }
  117. }
  118. /* When initial buffer is enough to store all output. */
  119. if (! p)
  120. p = buf;
  121. /* Pointer p must point out buffer. */
  122. buffer_put (vty->obuf, (u_char *) p, len);
  123. /* If p is not different with buf, it is allocated buffer. */
  124. if (p != buf)
  125. XFREE (MTYPE_VTY_OUT_BUF, p);
  126. }
  127. return len;
  128. }
  129. static int
  130. vty_log_out (struct vty *vty, const char *level, const char *proto_str,
  131. const char *format, struct timestamp_control *ctl, va_list va)
  132. {
  133. int ret;
  134. int len;
  135. char buf[1024];
  136. if (!ctl->already_rendered)
  137. {
  138. ctl->len = quagga_timestamp(ctl->precision, ctl->buf, sizeof(ctl->buf));
  139. ctl->already_rendered = 1;
  140. }
  141. if (ctl->len+1 >= sizeof(buf))
  142. return -1;
  143. memcpy(buf, ctl->buf, len = ctl->len);
  144. buf[len++] = ' ';
  145. buf[len] = '\0';
  146. if (level)
  147. ret = snprintf(buf+len, sizeof(buf)-len, "%s: %s: ", level, proto_str);
  148. else
  149. ret = snprintf(buf+len, sizeof(buf)-len, "%s: ", proto_str);
  150. if ((ret < 0) || ((size_t)(len += ret) >= sizeof(buf)))
  151. return -1;
  152. if (((ret = vsnprintf(buf+len, sizeof(buf)-len, format, va)) < 0) ||
  153. ((size_t)((len += ret)+2) > sizeof(buf)))
  154. return -1;
  155. buf[len++] = '\r';
  156. buf[len++] = '\n';
  157. if (write(vty->wfd, buf, len) < 0)
  158. {
  159. if (ERRNO_IO_RETRY(errno))
  160. /* Kernel buffer is full, probably too much debugging output, so just
  161. drop the data and ignore. */
  162. return -1;
  163. /* Fatal I/O error. */
  164. vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
  165. zlog_warn("%s: write failed to vty client fd %d, closing: %s",
  166. __func__, vty->fd, safe_strerror(errno));
  167. buffer_reset(vty->obuf);
  168. /* cannot call vty_close, because a parent routine may still try
  169. to access the vty struct */
  170. vty->status = VTY_CLOSE;
  171. shutdown(vty->fd, SHUT_RDWR);
  172. return -1;
  173. }
  174. return 0;
  175. }
  176. /* Output current time to the vty. */
  177. void
  178. vty_time_print (struct vty *vty, int cr)
  179. {
  180. char buf[QUAGGA_TIMESTAMP_LEN];
  181. if (quagga_timestamp(0, buf, sizeof(buf)) == 0)
  182. {
  183. zlog (NULL, LOG_INFO, "quagga_timestamp error");
  184. return;
  185. }
  186. if (cr)
  187. vty_out (vty, "%s\n", buf);
  188. else
  189. vty_out (vty, "%s ", buf);
  190. return;
  191. }
  192. /* Say hello to vty interface. */
  193. void
  194. vty_hello (struct vty *vty)
  195. {
  196. if (host.motdfile)
  197. {
  198. FILE *f;
  199. char buf[4096];
  200. f = fopen (host.motdfile, "r");
  201. if (f)
  202. {
  203. while (fgets (buf, sizeof (buf), f))
  204. {
  205. char *s;
  206. /* work backwards to ignore trailling isspace() */
  207. for (s = buf + strlen (buf); (s > buf) && isspace ((int)*(s - 1));
  208. s--);
  209. *s = '\0';
  210. vty_out (vty, "%s%s", buf, VTY_NEWLINE);
  211. }
  212. fclose (f);
  213. }
  214. else
  215. vty_out (vty, "MOTD file not found%s", VTY_NEWLINE);
  216. }
  217. else if (host.motd)
  218. vty_out (vty, "%s", host.motd);
  219. }
  220. /* Put out prompt and wait input from user. */
  221. static void
  222. vty_prompt (struct vty *vty)
  223. {
  224. struct utsname names;
  225. const char*hostname;
  226. if (vty->type == VTY_TERM)
  227. {
  228. hostname = host.name;
  229. if (!hostname)
  230. {
  231. uname (&names);
  232. hostname = names.nodename;
  233. }
  234. vty_out (vty, cmd_prompt (vty->node), hostname);
  235. }
  236. }
  237. /* Send WILL TELOPT_ECHO to remote server. */
  238. static void
  239. vty_will_echo (struct vty *vty)
  240. {
  241. unsigned char cmd[] = { IAC, WILL, TELOPT_ECHO, '\0' };
  242. vty_out (vty, "%s", cmd);
  243. }
  244. /* Make suppress Go-Ahead telnet option. */
  245. static void
  246. vty_will_suppress_go_ahead (struct vty *vty)
  247. {
  248. unsigned char cmd[] = { IAC, WILL, TELOPT_SGA, '\0' };
  249. vty_out (vty, "%s", cmd);
  250. }
  251. /* Make don't use linemode over telnet. */
  252. static void
  253. vty_dont_linemode (struct vty *vty)
  254. {
  255. unsigned char cmd[] = { IAC, DONT, TELOPT_LINEMODE, '\0' };
  256. vty_out (vty, "%s", cmd);
  257. }
  258. /* Use window size. */
  259. static void
  260. vty_do_window_size (struct vty *vty)
  261. {
  262. unsigned char cmd[] = { IAC, DO, TELOPT_NAWS, '\0' };
  263. vty_out (vty, "%s", cmd);
  264. }
  265. #if 0 /* Currently not used. */
  266. /* Make don't use lflow vty interface. */
  267. static void
  268. vty_dont_lflow_ahead (struct vty *vty)
  269. {
  270. unsigned char cmd[] = { IAC, DONT, TELOPT_LFLOW, '\0' };
  271. vty_out (vty, "%s", cmd);
  272. }
  273. #endif /* 0 */
  274. /* Allocate new vty struct. */
  275. struct vty *
  276. vty_new ()
  277. {
  278. struct vty *new = XCALLOC (MTYPE_VTY, sizeof (struct vty));
  279. new->obuf = buffer_new(0); /* Use default buffer size. */
  280. new->buf = XCALLOC (MTYPE_VTY, VTY_BUFSIZ);
  281. new->max = VTY_BUFSIZ;
  282. return new;
  283. }
  284. /* Authentication of vty */
  285. static void
  286. vty_auth (struct vty *vty, char *buf)
  287. {
  288. char *passwd = NULL;
  289. enum node_type next_node = 0;
  290. int fail;
  291. char *crypt (const char *, const char *);
  292. switch (vty->node)
  293. {
  294. case AUTH_NODE:
  295. if (host.encrypt)
  296. passwd = host.password_encrypt;
  297. else
  298. passwd = host.password;
  299. if (host.advanced)
  300. next_node = host.enable ? VIEW_NODE : ENABLE_NODE;
  301. else
  302. next_node = VIEW_NODE;
  303. break;
  304. case AUTH_ENABLE_NODE:
  305. if (host.encrypt)
  306. passwd = host.enable_encrypt;
  307. else
  308. passwd = host.enable;
  309. next_node = ENABLE_NODE;
  310. break;
  311. }
  312. if (passwd)
  313. {
  314. if (host.encrypt)
  315. fail = strcmp (crypt(buf, passwd), passwd);
  316. else
  317. fail = strcmp (buf, passwd);
  318. }
  319. else
  320. fail = 1;
  321. if (! fail)
  322. {
  323. vty->fail = 0;
  324. vty->node = next_node; /* Success ! */
  325. }
  326. else
  327. {
  328. vty->fail++;
  329. if (vty->fail >= 3)
  330. {
  331. if (vty->node == AUTH_NODE)
  332. {
  333. vty_out (vty, "%% Bad passwords, too many failures!%s", VTY_NEWLINE);
  334. vty->status = VTY_CLOSE;
  335. }
  336. else
  337. {
  338. /* AUTH_ENABLE_NODE */
  339. vty->fail = 0;
  340. vty_out (vty, "%% Bad enable passwords, too many failures!%s", VTY_NEWLINE);
  341. vty->node = restricted_mode ? RESTRICTED_NODE : VIEW_NODE;
  342. }
  343. }
  344. }
  345. }
  346. /* Command execution over the vty interface. */
  347. static int
  348. vty_command (struct vty *vty, char *buf)
  349. {
  350. int ret;
  351. vector vline;
  352. const char *protocolname;
  353. char *cp = NULL;
  354. /*
  355. * Log non empty command lines
  356. */
  357. if (do_log_commands)
  358. cp = buf;
  359. if (cp != NULL)
  360. {
  361. /* Skip white spaces. */
  362. while (isspace ((int) *cp) && *cp != '\0')
  363. cp++;
  364. }
  365. if (cp != NULL && *cp != '\0')
  366. {
  367. unsigned i;
  368. char vty_str[VTY_BUFSIZ];
  369. char prompt_str[VTY_BUFSIZ];
  370. /* format the base vty info */
  371. snprintf(vty_str, sizeof(vty_str), "vty[??]@%s", vty->address);
  372. if (vty)
  373. for (i = 0; i < vector_active (vtyvec); i++)
  374. if (vty == vector_slot (vtyvec, i))
  375. {
  376. snprintf(vty_str, sizeof(vty_str), "vty[%d]@%s",
  377. i, vty->address);
  378. break;
  379. }
  380. /* format the prompt */
  381. snprintf(prompt_str, sizeof(prompt_str), cmd_prompt (vty->node), vty_str);
  382. /* now log the command */
  383. zlog(NULL, LOG_ERR, "%s%s", prompt_str, buf);
  384. }
  385. /* Split readline string up into the vector */
  386. vline = cmd_make_strvec (buf);
  387. if (vline == NULL)
  388. return CMD_SUCCESS;
  389. #ifdef CONSUMED_TIME_CHECK
  390. {
  391. RUSAGE_T before;
  392. RUSAGE_T after;
  393. unsigned long realtime, cputime;
  394. GETRUSAGE(&before);
  395. #endif /* CONSUMED_TIME_CHECK */
  396. ret = cmd_execute_command (vline, vty, NULL, 0);
  397. /* Get the name of the protocol if any */
  398. if (zlog_default)
  399. protocolname = zlog_proto_names[zlog_default->protocol];
  400. else
  401. protocolname = zlog_proto_names[ZLOG_NONE];
  402. #ifdef CONSUMED_TIME_CHECK
  403. GETRUSAGE(&after);
  404. if ((realtime = thread_consumed_time(&after, &before, &cputime)) >
  405. CONSUMED_TIME_CHECK)
  406. /* Warn about CPU hog that must be fixed. */
  407. zlog_warn("SLOW COMMAND: command took %lums (cpu time %lums): %s",
  408. realtime/1000, cputime/1000, buf);
  409. }
  410. #endif /* CONSUMED_TIME_CHECK */
  411. if (ret != CMD_SUCCESS)
  412. switch (ret)
  413. {
  414. case CMD_WARNING:
  415. if (vty->type == VTY_FILE)
  416. vty_out (vty, "Warning...%s", VTY_NEWLINE);
  417. break;
  418. case CMD_ERR_AMBIGUOUS:
  419. vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
  420. break;
  421. case CMD_ERR_NO_MATCH:
  422. vty_out (vty, "%% [%s] Unknown command: %s%s", protocolname, buf, VTY_NEWLINE);
  423. break;
  424. case CMD_ERR_INCOMPLETE:
  425. vty_out (vty, "%% Command incomplete.%s", VTY_NEWLINE);
  426. break;
  427. }
  428. cmd_free_strvec (vline);
  429. return ret;
  430. }
  431. static const char telnet_backward_char = 0x08;
  432. static const char telnet_space_char = ' ';
  433. /* Basic function to write buffer to vty. */
  434. static void
  435. vty_write (struct vty *vty, const char *buf, size_t nbytes)
  436. {
  437. if ((vty->node == AUTH_NODE) || (vty->node == AUTH_ENABLE_NODE))
  438. return;
  439. /* Should we do buffering here ? And make vty_flush (vty) ? */
  440. buffer_put (vty->obuf, buf, nbytes);
  441. }
  442. /* Basic function to insert character into vty. */
  443. static void
  444. vty_self_insert (struct vty *vty, char c)
  445. {
  446. int i;
  447. int length;
  448. if (vty->length + 1 > VTY_BUFSIZ)
  449. return;
  450. length = vty->length - vty->cp;
  451. memmove (&vty->buf[vty->cp + 1], &vty->buf[vty->cp], length);
  452. vty->buf[vty->cp] = c;
  453. vty_write (vty, &vty->buf[vty->cp], length + 1);
  454. for (i = 0; i < length; i++)
  455. vty_write (vty, &telnet_backward_char, 1);
  456. vty->cp++;
  457. vty->length++;
  458. }
  459. /* Self insert character 'c' in overwrite mode. */
  460. static void
  461. vty_self_insert_overwrite (struct vty *vty, char c)
  462. {
  463. if (vty->cp == vty->length)
  464. {
  465. vty_self_insert (vty, c);
  466. return;
  467. }
  468. vty->buf[vty->cp++] = c;
  469. vty_write (vty, &c, 1);
  470. }
  471. /**
  472. * Insert a string into vty->buf at the current cursor position.
  473. *
  474. * If the resultant string would be larger than VTY_BUFSIZ it is
  475. * truncated to fit.
  476. */
  477. static void
  478. vty_insert_word_overwrite (struct vty *vty, char *str)
  479. {
  480. size_t nwrite = MIN ((int) strlen (str), VTY_BUFSIZ - vty->cp);
  481. vty_write (vty, str, nwrite);
  482. strncpy (&vty->buf[vty->cp], str, nwrite);
  483. vty->cp += nwrite;
  484. vty->length = vty->cp;
  485. }
  486. /* Forward character. */
  487. static void
  488. vty_forward_char (struct vty *vty)
  489. {
  490. if (vty->cp < vty->length)
  491. {
  492. vty_write (vty, &vty->buf[vty->cp], 1);
  493. vty->cp++;
  494. }
  495. }
  496. /* Backward character. */
  497. static void
  498. vty_backward_char (struct vty *vty)
  499. {
  500. if (vty->cp > 0)
  501. {
  502. vty->cp--;
  503. vty_write (vty, &telnet_backward_char, 1);
  504. }
  505. }
  506. /* Move to the beginning of the line. */
  507. static void
  508. vty_beginning_of_line (struct vty *vty)
  509. {
  510. while (vty->cp)
  511. vty_backward_char (vty);
  512. }
  513. /* Move to the end of the line. */
  514. static void
  515. vty_end_of_line (struct vty *vty)
  516. {
  517. while (vty->cp < vty->length)
  518. vty_forward_char (vty);
  519. }
  520. static void vty_kill_line_from_beginning (struct vty *);
  521. static void vty_redraw_line (struct vty *);
  522. /* Print command line history. This function is called from
  523. vty_next_line and vty_previous_line. */
  524. static void
  525. vty_history_print (struct vty *vty)
  526. {
  527. int length;
  528. vty_kill_line_from_beginning (vty);
  529. /* Get previous line from history buffer */
  530. length = strlen (vty->hist[vty->hp]);
  531. memcpy (vty->buf, vty->hist[vty->hp], length);
  532. vty->cp = vty->length = length;
  533. /* Redraw current line */
  534. vty_redraw_line (vty);
  535. }
  536. /* Show next command line history. */
  537. static void
  538. vty_next_line (struct vty *vty)
  539. {
  540. int try_index;
  541. if (vty->hp == vty->hindex)
  542. return;
  543. /* Try is there history exist or not. */
  544. try_index = vty->hp;
  545. if (try_index == (VTY_MAXHIST - 1))
  546. try_index = 0;
  547. else
  548. try_index++;
  549. /* If there is not history return. */
  550. if (vty->hist[try_index] == NULL)
  551. return;
  552. else
  553. vty->hp = try_index;
  554. vty_history_print (vty);
  555. }
  556. /* Show previous command line history. */
  557. static void
  558. vty_previous_line (struct vty *vty)
  559. {
  560. int try_index;
  561. try_index = vty->hp;
  562. if (try_index == 0)
  563. try_index = VTY_MAXHIST - 1;
  564. else
  565. try_index--;
  566. if (vty->hist[try_index] == NULL)
  567. return;
  568. else
  569. vty->hp = try_index;
  570. vty_history_print (vty);
  571. }
  572. /* This function redraw all of the command line character. */
  573. static void
  574. vty_redraw_line (struct vty *vty)
  575. {
  576. vty_write (vty, vty->buf, vty->length);
  577. vty->cp = vty->length;
  578. }
  579. /* Forward word. */
  580. static void
  581. vty_forward_word (struct vty *vty)
  582. {
  583. while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
  584. vty_forward_char (vty);
  585. while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
  586. vty_forward_char (vty);
  587. }
  588. /* Backward word without skipping training space. */
  589. static void
  590. vty_backward_pure_word (struct vty *vty)
  591. {
  592. while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
  593. vty_backward_char (vty);
  594. }
  595. /* Backward word. */
  596. static void
  597. vty_backward_word (struct vty *vty)
  598. {
  599. while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
  600. vty_backward_char (vty);
  601. while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
  602. vty_backward_char (vty);
  603. }
  604. /* When '^D' is typed at the beginning of the line we move to the down
  605. level. */
  606. static void
  607. vty_down_level (struct vty *vty)
  608. {
  609. vty_out (vty, "%s", VTY_NEWLINE);
  610. (*config_exit_cmd.func)(NULL, vty, 0, NULL);
  611. vty_prompt (vty);
  612. vty->cp = 0;
  613. }
  614. /* When '^Z' is received from vty, move down to the enable mode. */
  615. static void
  616. vty_end_config (struct vty *vty)
  617. {
  618. vty_out (vty, "%s", VTY_NEWLINE);
  619. switch (vty->node)
  620. {
  621. case VIEW_NODE:
  622. case ENABLE_NODE:
  623. case RESTRICTED_NODE:
  624. /* Nothing to do. */
  625. break;
  626. case CONFIG_NODE:
  627. case INTERFACE_NODE:
  628. case ZEBRA_NODE:
  629. case RIP_NODE:
  630. case RIPNG_NODE:
  631. case BABEL_NODE:
  632. case BGP_NODE:
  633. case BGP_VPNV4_NODE:
  634. case BGP_VPNV6_NODE:
  635. case BGP_ENCAP_NODE:
  636. case BGP_ENCAPV6_NODE:
  637. case BGP_IPV4_NODE:
  638. case BGP_IPV4M_NODE:
  639. case BGP_IPV6_NODE:
  640. case BGP_IPV6M_NODE:
  641. case RMAP_NODE:
  642. case OSPF_NODE:
  643. case OSPF6_NODE:
  644. case ISIS_NODE:
  645. case KEYCHAIN_NODE:
  646. case KEYCHAIN_KEY_NODE:
  647. case MASC_NODE:
  648. case PIM_NODE:
  649. case VTY_NODE:
  650. vty_config_unlock (vty);
  651. vty->node = ENABLE_NODE;
  652. break;
  653. default:
  654. /* Unknown node, we have to ignore it. */
  655. break;
  656. }
  657. vty_prompt (vty);
  658. vty->cp = 0;
  659. }
  660. /* Delete a charcter at the current point. */
  661. static void
  662. vty_delete_char (struct vty *vty)
  663. {
  664. int i;
  665. int size;
  666. if (vty->length == 0)
  667. {
  668. vty_down_level (vty);
  669. return;
  670. }
  671. if (vty->cp == vty->length)
  672. return; /* completion need here? */
  673. size = vty->length - vty->cp;
  674. vty->length--;
  675. memmove (&vty->buf[vty->cp], &vty->buf[vty->cp + 1], size - 1);
  676. vty->buf[vty->length] = '\0';
  677. if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
  678. return;
  679. vty_write (vty, &vty->buf[vty->cp], size - 1);
  680. vty_write (vty, &telnet_space_char, 1);
  681. for (i = 0; i < size; i++)
  682. vty_write (vty, &telnet_backward_char, 1);
  683. }
  684. /* Delete a character before the point. */
  685. static void
  686. vty_delete_backward_char (struct vty *vty)
  687. {
  688. if (vty->cp == 0)
  689. return;
  690. vty_backward_char (vty);
  691. vty_delete_char (vty);
  692. }
  693. /* Kill rest of line from current point. */
  694. static void
  695. vty_kill_line (struct vty *vty)
  696. {
  697. int i;
  698. int size;
  699. size = vty->length - vty->cp;
  700. if (size == 0)
  701. return;
  702. for (i = 0; i < size; i++)
  703. vty_write (vty, &telnet_space_char, 1);
  704. for (i = 0; i < size; i++)
  705. vty_write (vty, &telnet_backward_char, 1);
  706. memset (&vty->buf[vty->cp], 0, size);
  707. vty->length = vty->cp;
  708. }
  709. /* Kill line from the beginning. */
  710. static void
  711. vty_kill_line_from_beginning (struct vty *vty)
  712. {
  713. vty_beginning_of_line (vty);
  714. vty_kill_line (vty);
  715. }
  716. /* Delete a word before the point. */
  717. static void
  718. vty_forward_kill_word (struct vty *vty)
  719. {
  720. while (vty->cp != vty->length && vty->buf[vty->cp] == ' ')
  721. vty_delete_char (vty);
  722. while (vty->cp != vty->length && vty->buf[vty->cp] != ' ')
  723. vty_delete_char (vty);
  724. }
  725. /* Delete a word before the point. */
  726. static void
  727. vty_backward_kill_word (struct vty *vty)
  728. {
  729. while (vty->cp > 0 && vty->buf[vty->cp - 1] == ' ')
  730. vty_delete_backward_char (vty);
  731. while (vty->cp > 0 && vty->buf[vty->cp - 1] != ' ')
  732. vty_delete_backward_char (vty);
  733. }
  734. /* Transpose chars before or at the point. */
  735. static void
  736. vty_transpose_chars (struct vty *vty)
  737. {
  738. char c1, c2;
  739. /* If length is short or point is near by the beginning of line then
  740. return. */
  741. if (vty->length < 2 || vty->cp < 1)
  742. return;
  743. /* In case of point is located at the end of the line. */
  744. if (vty->cp == vty->length)
  745. {
  746. c1 = vty->buf[vty->cp - 1];
  747. c2 = vty->buf[vty->cp - 2];
  748. vty_backward_char (vty);
  749. vty_backward_char (vty);
  750. vty_self_insert_overwrite (vty, c1);
  751. vty_self_insert_overwrite (vty, c2);
  752. }
  753. else
  754. {
  755. c1 = vty->buf[vty->cp];
  756. c2 = vty->buf[vty->cp - 1];
  757. vty_backward_char (vty);
  758. vty_self_insert_overwrite (vty, c1);
  759. vty_self_insert_overwrite (vty, c2);
  760. }
  761. }
  762. /* Do completion at vty interface. */
  763. static void
  764. vty_complete_command (struct vty *vty)
  765. {
  766. int i;
  767. int ret;
  768. char **matched = NULL;
  769. vector vline;
  770. if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
  771. return;
  772. vline = cmd_make_strvec (vty->buf);
  773. if (vline == NULL)
  774. return;
  775. /* In case of 'help \t'. */
  776. if (isspace ((int) vty->buf[vty->length - 1]))
  777. vector_set (vline, NULL);
  778. matched = cmd_complete_command_lib (vline, vty, &ret, 1);
  779. cmd_free_strvec (vline);
  780. vty_out (vty, "%s", VTY_NEWLINE);
  781. switch (ret)
  782. {
  783. case CMD_ERR_AMBIGUOUS:
  784. vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
  785. vty_prompt (vty);
  786. vty_redraw_line (vty);
  787. break;
  788. case CMD_ERR_NO_MATCH:
  789. /* vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE); */
  790. vty_prompt (vty);
  791. vty_redraw_line (vty);
  792. break;
  793. case CMD_COMPLETE_FULL_MATCH:
  794. vty_prompt (vty);
  795. vty_redraw_line (vty);
  796. vty_backward_pure_word (vty);
  797. vty_insert_word_overwrite (vty, matched[0]);
  798. vty_self_insert (vty, ' ');
  799. XFREE (MTYPE_TMP, matched[0]);
  800. break;
  801. case CMD_COMPLETE_MATCH:
  802. vty_prompt (vty);
  803. vty_redraw_line (vty);
  804. vty_backward_pure_word (vty);
  805. vty_insert_word_overwrite (vty, matched[0]);
  806. XFREE (MTYPE_TMP, matched[0]);
  807. vector_only_index_free (matched);
  808. return;
  809. break;
  810. case CMD_COMPLETE_LIST_MATCH:
  811. for (i = 0; matched[i] != NULL; i++)
  812. {
  813. if (i != 0 && ((i % 6) == 0))
  814. vty_out (vty, "%s", VTY_NEWLINE);
  815. vty_out (vty, "%-10s ", matched[i]);
  816. XFREE (MTYPE_TMP, matched[i]);
  817. }
  818. vty_out (vty, "%s", VTY_NEWLINE);
  819. vty_prompt (vty);
  820. vty_redraw_line (vty);
  821. break;
  822. case CMD_ERR_NOTHING_TODO:
  823. vty_prompt (vty);
  824. vty_redraw_line (vty);
  825. break;
  826. default:
  827. break;
  828. }
  829. if (matched)
  830. vector_only_index_free (matched);
  831. }
  832. static void
  833. vty_describe_fold (struct vty *vty, int cmd_width,
  834. unsigned int desc_width, struct cmd_token *token)
  835. {
  836. char *buf;
  837. const char *cmd, *p;
  838. int pos;
  839. cmd = token->cmd[0] == '.' ? token->cmd + 1 : token->cmd;
  840. if (desc_width <= 0)
  841. {
  842. vty_out (vty, " %-*s %s%s", cmd_width, cmd, token->desc, VTY_NEWLINE);
  843. return;
  844. }
  845. buf = XCALLOC (MTYPE_TMP, strlen (token->desc) + 1);
  846. for (p = token->desc; strlen (p) > desc_width; p += pos + 1)
  847. {
  848. for (pos = desc_width; pos > 0; pos--)
  849. if (*(p + pos) == ' ')
  850. break;
  851. if (pos == 0)
  852. break;
  853. strncpy (buf, p, pos);
  854. buf[pos] = '\0';
  855. vty_out (vty, " %-*s %s%s", cmd_width, cmd, buf, VTY_NEWLINE);
  856. cmd = "";
  857. }
  858. vty_out (vty, " %-*s %s%s", cmd_width, cmd, p, VTY_NEWLINE);
  859. XFREE (MTYPE_TMP, buf);
  860. }
  861. /* Describe matched command function. */
  862. static void
  863. vty_describe_command (struct vty *vty)
  864. {
  865. int ret;
  866. vector vline;
  867. vector describe;
  868. unsigned int i, width, desc_width;
  869. struct cmd_token *token, *token_cr = NULL;
  870. vline = cmd_make_strvec (vty->buf);
  871. /* In case of '> ?'. */
  872. if (vline == NULL)
  873. {
  874. vline = vector_init (1);
  875. vector_set (vline, NULL);
  876. }
  877. else
  878. if (isspace ((int) vty->buf[vty->length - 1]))
  879. vector_set (vline, NULL);
  880. describe = cmd_describe_command (vline, vty, &ret);
  881. vty_out (vty, "%s", VTY_NEWLINE);
  882. /* Ambiguous error. */
  883. switch (ret)
  884. {
  885. case CMD_ERR_AMBIGUOUS:
  886. vty_out (vty, "%% Ambiguous command.%s", VTY_NEWLINE);
  887. goto out;
  888. break;
  889. case CMD_ERR_NO_MATCH:
  890. vty_out (vty, "%% There is no matched command.%s", VTY_NEWLINE);
  891. goto out;
  892. break;
  893. }
  894. /* Get width of command string. */
  895. width = 0;
  896. for (i = 0; i < vector_active (describe); i++)
  897. if ((token = vector_slot (describe, i)) != NULL)
  898. {
  899. unsigned int len;
  900. if (token->cmd[0] == '\0')
  901. continue;
  902. len = strlen (token->cmd);
  903. if (token->cmd[0] == '.')
  904. len--;
  905. if (width < len)
  906. width = len;
  907. }
  908. /* Get width of description string. */
  909. desc_width = vty->width - (width + 6);
  910. /* Print out description. */
  911. for (i = 0; i < vector_active (describe); i++)
  912. if ((token = vector_slot (describe, i)) != NULL)
  913. {
  914. if (token->cmd[0] == '\0')
  915. continue;
  916. if (strcmp (token->cmd, command_cr) == 0)
  917. {
  918. token_cr = token;
  919. continue;
  920. }
  921. if (!token->desc)
  922. vty_out (vty, " %-s%s",
  923. token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
  924. VTY_NEWLINE);
  925. else if (desc_width >= strlen (token->desc))
  926. vty_out (vty, " %-*s %s%s", width,
  927. token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
  928. token->desc, VTY_NEWLINE);
  929. else
  930. vty_describe_fold (vty, width, desc_width, token);
  931. #if 0
  932. vty_out (vty, " %-*s %s%s", width
  933. desc->cmd[0] == '.' ? desc->cmd + 1 : desc->cmd,
  934. desc->str ? desc->str : "", VTY_NEWLINE);
  935. #endif /* 0 */
  936. }
  937. if ((token = token_cr))
  938. {
  939. if (!token->desc)
  940. vty_out (vty, " %-s%s",
  941. token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
  942. VTY_NEWLINE);
  943. else if (desc_width >= strlen (token->desc))
  944. vty_out (vty, " %-*s %s%s", width,
  945. token->cmd[0] == '.' ? token->cmd + 1 : token->cmd,
  946. token->desc, VTY_NEWLINE);
  947. else
  948. vty_describe_fold (vty, width, desc_width, token);
  949. }
  950. out:
  951. cmd_free_strvec (vline);
  952. if (describe)
  953. vector_free (describe);
  954. vty_prompt (vty);
  955. vty_redraw_line (vty);
  956. }
  957. static void
  958. vty_clear_buf (struct vty *vty)
  959. {
  960. memset (vty->buf, 0, vty->max);
  961. }
  962. /* ^C stop current input and do not add command line to the history. */
  963. static void
  964. vty_stop_input (struct vty *vty)
  965. {
  966. vty->cp = vty->length = 0;
  967. vty_clear_buf (vty);
  968. vty_out (vty, "%s", VTY_NEWLINE);
  969. switch (vty->node)
  970. {
  971. case VIEW_NODE:
  972. case ENABLE_NODE:
  973. case RESTRICTED_NODE:
  974. /* Nothing to do. */
  975. break;
  976. case CONFIG_NODE:
  977. case INTERFACE_NODE:
  978. case ZEBRA_NODE:
  979. case RIP_NODE:
  980. case RIPNG_NODE:
  981. case BABEL_NODE:
  982. case BGP_NODE:
  983. case RMAP_NODE:
  984. case OSPF_NODE:
  985. case OSPF6_NODE:
  986. case ISIS_NODE:
  987. case KEYCHAIN_NODE:
  988. case KEYCHAIN_KEY_NODE:
  989. case MASC_NODE:
  990. case PIM_NODE:
  991. case VTY_NODE:
  992. vty_config_unlock (vty);
  993. vty->node = ENABLE_NODE;
  994. break;
  995. default:
  996. /* Unknown node, we have to ignore it. */
  997. break;
  998. }
  999. vty_prompt (vty);
  1000. /* Set history pointer to the latest one. */
  1001. vty->hp = vty->hindex;
  1002. }
  1003. /* Add current command line to the history buffer. */
  1004. static void
  1005. vty_hist_add (struct vty *vty)
  1006. {
  1007. int index;
  1008. if (vty->length == 0)
  1009. return;
  1010. index = vty->hindex ? vty->hindex - 1 : VTY_MAXHIST - 1;
  1011. /* Ignore the same string as previous one. */
  1012. if (vty->hist[index])
  1013. if (strcmp (vty->buf, vty->hist[index]) == 0)
  1014. {
  1015. vty->hp = vty->hindex;
  1016. return;
  1017. }
  1018. /* Insert history entry. */
  1019. if (vty->hist[vty->hindex])
  1020. XFREE (MTYPE_VTY_HIST, vty->hist[vty->hindex]);
  1021. vty->hist[vty->hindex] = XSTRDUP (MTYPE_VTY_HIST, vty->buf);
  1022. /* History index rotation. */
  1023. vty->hindex++;
  1024. if (vty->hindex == VTY_MAXHIST)
  1025. vty->hindex = 0;
  1026. vty->hp = vty->hindex;
  1027. }
  1028. /* #define TELNET_OPTION_DEBUG */
  1029. /* Get telnet window size. */
  1030. static int
  1031. vty_telnet_option (struct vty *vty, unsigned char *buf, int nbytes)
  1032. {
  1033. #ifdef TELNET_OPTION_DEBUG
  1034. int i;
  1035. for (i = 0; i < nbytes; i++)
  1036. {
  1037. switch (buf[i])
  1038. {
  1039. case IAC:
  1040. vty_out (vty, "IAC ");
  1041. break;
  1042. case WILL:
  1043. vty_out (vty, "WILL ");
  1044. break;
  1045. case WONT:
  1046. vty_out (vty, "WONT ");
  1047. break;
  1048. case DO:
  1049. vty_out (vty, "DO ");
  1050. break;
  1051. case DONT:
  1052. vty_out (vty, "DONT ");
  1053. break;
  1054. case SB:
  1055. vty_out (vty, "SB ");
  1056. break;
  1057. case SE:
  1058. vty_out (vty, "SE ");
  1059. break;
  1060. case TELOPT_ECHO:
  1061. vty_out (vty, "TELOPT_ECHO %s", VTY_NEWLINE);
  1062. break;
  1063. case TELOPT_SGA:
  1064. vty_out (vty, "TELOPT_SGA %s", VTY_NEWLINE);
  1065. break;
  1066. case TELOPT_NAWS:
  1067. vty_out (vty, "TELOPT_NAWS %s", VTY_NEWLINE);
  1068. break;
  1069. default:
  1070. vty_out (vty, "%x ", buf[i]);
  1071. break;
  1072. }
  1073. }
  1074. vty_out (vty, "%s", VTY_NEWLINE);
  1075. #endif /* TELNET_OPTION_DEBUG */
  1076. switch (buf[0])
  1077. {
  1078. case SB:
  1079. vty->sb_len = 0;
  1080. vty->iac_sb_in_progress = 1;
  1081. return 0;
  1082. break;
  1083. case SE:
  1084. {
  1085. if (!vty->iac_sb_in_progress)
  1086. return 0;
  1087. if ((vty->sb_len == 0) || (vty->sb_buf[0] == '\0'))
  1088. {
  1089. vty->iac_sb_in_progress = 0;
  1090. return 0;
  1091. }
  1092. switch (vty->sb_buf[0])
  1093. {
  1094. case TELOPT_NAWS:
  1095. if (vty->sb_len != TELNET_NAWS_SB_LEN)
  1096. zlog_warn("RFC 1073 violation detected: telnet NAWS option "
  1097. "should send %d characters, but we received %lu",
  1098. TELNET_NAWS_SB_LEN, (u_long)vty->sb_len);
  1099. else if (sizeof(vty->sb_buf) < TELNET_NAWS_SB_LEN)
  1100. zlog_err("Bug detected: sizeof(vty->sb_buf) %lu < %d, "
  1101. "too small to handle the telnet NAWS option",
  1102. (u_long)sizeof(vty->sb_buf), TELNET_NAWS_SB_LEN);
  1103. else
  1104. {
  1105. vty->width = ((vty->sb_buf[1] << 8)|vty->sb_buf[2]);
  1106. vty->height = ((vty->sb_buf[3] << 8)|vty->sb_buf[4]);
  1107. #ifdef TELNET_OPTION_DEBUG
  1108. vty_out(vty, "TELNET NAWS window size negotiation completed: "
  1109. "width %d, height %d%s",
  1110. vty->width, vty->height, VTY_NEWLINE);
  1111. #endif
  1112. }
  1113. break;
  1114. }
  1115. vty->iac_sb_in_progress = 0;
  1116. return 0;
  1117. break;
  1118. }
  1119. default:
  1120. break;
  1121. }
  1122. return 1;
  1123. }
  1124. /* Execute current command line. */
  1125. static int
  1126. vty_execute (struct vty *vty)
  1127. {
  1128. int ret;
  1129. ret = CMD_SUCCESS;
  1130. switch (vty->node)
  1131. {
  1132. case AUTH_NODE:
  1133. case AUTH_ENABLE_NODE:
  1134. vty_auth (vty, vty->buf);
  1135. break;
  1136. default:
  1137. ret = vty_command (vty, vty->buf);
  1138. if (vty->type == VTY_TERM)
  1139. vty_hist_add (vty);
  1140. break;
  1141. }
  1142. /* Clear command line buffer. */
  1143. vty->cp = vty->length = 0;
  1144. vty_clear_buf (vty);
  1145. if (vty->status != VTY_CLOSE )
  1146. vty_prompt (vty);
  1147. return ret;
  1148. }
  1149. #define CONTROL(X) ((X) - '@')
  1150. #define VTY_NORMAL 0
  1151. #define VTY_PRE_ESCAPE 1
  1152. #define VTY_ESCAPE 2
  1153. /* Escape character command map. */
  1154. static void
  1155. vty_escape_map (unsigned char c, struct vty *vty)
  1156. {
  1157. switch (c)
  1158. {
  1159. case ('A'):
  1160. vty_previous_line (vty);
  1161. break;
  1162. case ('B'):
  1163. vty_next_line (vty);
  1164. break;
  1165. case ('C'):
  1166. vty_forward_char (vty);
  1167. break;
  1168. case ('D'):
  1169. vty_backward_char (vty);
  1170. break;
  1171. default:
  1172. break;
  1173. }
  1174. /* Go back to normal mode. */
  1175. vty->escape = VTY_NORMAL;
  1176. }
  1177. /* Quit print out to the buffer. */
  1178. static void
  1179. vty_buffer_reset (struct vty *vty)
  1180. {
  1181. buffer_reset (vty->obuf);
  1182. vty_prompt (vty);
  1183. vty_redraw_line (vty);
  1184. }
  1185. /* Read data via vty socket. */
  1186. static int
  1187. vty_read (struct thread *thread)
  1188. {
  1189. int i;
  1190. int nbytes;
  1191. unsigned char buf[VTY_READ_BUFSIZ];
  1192. int vty_sock = THREAD_FD (thread);
  1193. struct vty *vty = THREAD_ARG (thread);
  1194. vty->t_read = NULL;
  1195. /* Read raw data from socket */
  1196. if ((nbytes = read (vty->fd, buf, VTY_READ_BUFSIZ)) <= 0)
  1197. {
  1198. if (nbytes < 0)
  1199. {
  1200. if (ERRNO_IO_RETRY(errno))
  1201. {
  1202. vty_event (VTY_READ, vty_sock, vty);
  1203. return 0;
  1204. }
  1205. vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
  1206. zlog_warn("%s: read error on vty client fd %d, closing: %s",
  1207. __func__, vty->fd, safe_strerror(errno));
  1208. buffer_reset(vty->obuf);
  1209. }
  1210. vty->status = VTY_CLOSE;
  1211. }
  1212. for (i = 0; i < nbytes; i++)
  1213. {
  1214. if (buf[i] == IAC)
  1215. {
  1216. if (!vty->iac)
  1217. {
  1218. vty->iac = 1;
  1219. continue;
  1220. }
  1221. else
  1222. {
  1223. vty->iac = 0;
  1224. }
  1225. }
  1226. if (vty->iac_sb_in_progress && !vty->iac)
  1227. {
  1228. if (vty->sb_len < sizeof(vty->sb_buf))
  1229. vty->sb_buf[vty->sb_len] = buf[i];
  1230. vty->sb_len++;
  1231. continue;
  1232. }
  1233. if (vty->iac)
  1234. {
  1235. /* In case of telnet command */
  1236. int ret = 0;
  1237. ret = vty_telnet_option (vty, buf + i, nbytes - i);
  1238. vty->iac = 0;
  1239. i += ret;
  1240. continue;
  1241. }
  1242. if (vty->status == VTY_MORE)
  1243. {
  1244. switch (buf[i])
  1245. {
  1246. case CONTROL('C'):
  1247. case 'q':
  1248. case 'Q':
  1249. vty_buffer_reset (vty);
  1250. break;
  1251. #if 0 /* More line does not work for "show ip bgp". */
  1252. case '\n':
  1253. case '\r':
  1254. vty->status = VTY_MORELINE;
  1255. break;
  1256. #endif
  1257. default:
  1258. break;
  1259. }
  1260. continue;
  1261. }
  1262. /* Escape character. */
  1263. if (vty->escape == VTY_ESCAPE)
  1264. {
  1265. vty_escape_map (buf[i], vty);
  1266. continue;
  1267. }
  1268. /* Pre-escape status. */
  1269. if (vty->escape == VTY_PRE_ESCAPE)
  1270. {
  1271. switch (buf[i])
  1272. {
  1273. case '[':
  1274. vty->escape = VTY_ESCAPE;
  1275. break;
  1276. case 'b':
  1277. vty_backward_word (vty);
  1278. vty->escape = VTY_NORMAL;
  1279. break;
  1280. case 'f':
  1281. vty_forward_word (vty);
  1282. vty->escape = VTY_NORMAL;
  1283. break;
  1284. case 'd':
  1285. vty_forward_kill_word (vty);
  1286. vty->escape = VTY_NORMAL;
  1287. break;
  1288. case CONTROL('H'):
  1289. case 0x7f:
  1290. vty_backward_kill_word (vty);
  1291. vty->escape = VTY_NORMAL;
  1292. break;
  1293. default:
  1294. vty->escape = VTY_NORMAL;
  1295. break;
  1296. }
  1297. continue;
  1298. }
  1299. switch (buf[i])
  1300. {
  1301. case CONTROL('A'):
  1302. vty_beginning_of_line (vty);
  1303. break;
  1304. case CONTROL('B'):
  1305. vty_backward_char (vty);
  1306. break;
  1307. case CONTROL('C'):
  1308. vty_stop_input (vty);
  1309. break;
  1310. case CONTROL('D'):
  1311. vty_delete_char (vty);
  1312. break;
  1313. case CONTROL('E'):
  1314. vty_end_of_line (vty);
  1315. break;
  1316. case CONTROL('F'):
  1317. vty_forward_char (vty);
  1318. break;
  1319. case CONTROL('H'):
  1320. case 0x7f:
  1321. vty_delete_backward_char (vty);
  1322. break;
  1323. case CONTROL('K'):
  1324. vty_kill_line (vty);
  1325. break;
  1326. case CONTROL('N'):
  1327. vty_next_line (vty);
  1328. break;
  1329. case CONTROL('P'):
  1330. vty_previous_line (vty);
  1331. break;
  1332. case CONTROL('T'):
  1333. vty_transpose_chars (vty);
  1334. break;
  1335. case CONTROL('U'):
  1336. vty_kill_line_from_beginning (vty);
  1337. break;
  1338. case CONTROL('W'):
  1339. vty_backward_kill_word (vty);
  1340. break;
  1341. case CONTROL('Z'):
  1342. vty_end_config (vty);
  1343. break;
  1344. case '\n':
  1345. case '\r':
  1346. vty_out (vty, "%s", VTY_NEWLINE);
  1347. vty_execute (vty);
  1348. break;
  1349. case '\t':
  1350. vty_complete_command (vty);
  1351. break;
  1352. case '?':
  1353. if (vty->node == AUTH_NODE || vty->node == AUTH_ENABLE_NODE)
  1354. vty_self_insert (vty, buf[i]);
  1355. else
  1356. vty_describe_command (vty);
  1357. break;
  1358. case '\033':
  1359. if (i + 1 < nbytes && buf[i + 1] == '[')
  1360. {
  1361. vty->escape = VTY_ESCAPE;
  1362. i++;
  1363. }
  1364. else
  1365. vty->escape = VTY_PRE_ESCAPE;
  1366. break;
  1367. default:
  1368. if (buf[i] > 31 && buf[i] < 127)
  1369. vty_self_insert (vty, buf[i]);
  1370. break;
  1371. }
  1372. }
  1373. /* Check status. */
  1374. if (vty->status == VTY_CLOSE)
  1375. vty_close (vty);
  1376. else
  1377. {
  1378. vty_event (VTY_WRITE, vty->wfd, vty);
  1379. vty_event (VTY_READ, vty_sock, vty);
  1380. }
  1381. return 0;
  1382. }
  1383. /* Flush buffer to the vty. */
  1384. static int
  1385. vty_flush (struct thread *thread)
  1386. {
  1387. int erase;
  1388. buffer_status_t flushrc;
  1389. int vty_sock = THREAD_FD (thread);
  1390. struct vty *vty = THREAD_ARG (thread);
  1391. vty->t_write = NULL;
  1392. /* Tempolary disable read thread. */
  1393. if ((vty->lines == 0) && vty->t_read)
  1394. {
  1395. thread_cancel (vty->t_read);
  1396. vty->t_read = NULL;
  1397. }
  1398. /* Function execution continue. */
  1399. erase = ((vty->status == VTY_MORE || vty->status == VTY_MORELINE));
  1400. /* N.B. if width is 0, that means we don't know the window size. */
  1401. if ((vty->lines == 0) || (vty->width == 0) || (vty->height == 0))
  1402. flushrc = buffer_flush_available(vty->obuf, vty_sock);
  1403. else if (vty->status == VTY_MORELINE)
  1404. flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width,
  1405. 1, erase, 0);
  1406. else
  1407. flushrc = buffer_flush_window(vty->obuf, vty_sock, vty->width,
  1408. vty->lines >= 0 ? vty->lines :
  1409. vty->height,
  1410. erase, 0);
  1411. switch (flushrc)
  1412. {
  1413. case BUFFER_ERROR:
  1414. vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
  1415. zlog_warn("buffer_flush failed on vty client fd %d, closing",
  1416. vty->fd);
  1417. buffer_reset(vty->obuf);
  1418. vty_close(vty);
  1419. return 0;
  1420. case BUFFER_EMPTY:
  1421. if (vty->status == VTY_CLOSE)
  1422. vty_close (vty);
  1423. else
  1424. {
  1425. vty->status = VTY_NORMAL;
  1426. if (vty->lines == 0)
  1427. vty_event (VTY_READ, vty_sock, vty);
  1428. }
  1429. break;
  1430. case BUFFER_PENDING:
  1431. /* There is more data waiting to be written. */
  1432. vty->status = VTY_MORE;
  1433. if (vty->lines == 0)
  1434. vty_event (VTY_WRITE, vty_sock, vty);
  1435. break;
  1436. }
  1437. return 0;
  1438. }
  1439. /* allocate and initialise vty */
  1440. static struct vty *
  1441. vty_new_init (int vty_sock)
  1442. {
  1443. struct vty *vty;
  1444. vty = vty_new ();
  1445. vty->fd = vty_sock;
  1446. vty->wfd = vty_sock;
  1447. vty->type = VTY_TERM;
  1448. vty->node = AUTH_NODE;
  1449. vty->fail = 0;
  1450. vty->cp = 0;
  1451. vty_clear_buf (vty);
  1452. vty->length = 0;
  1453. memset (vty->hist, 0, sizeof (vty->hist));
  1454. vty->hp = 0;
  1455. vty->hindex = 0;
  1456. vector_set_index (vtyvec, vty_sock, vty);
  1457. vty->status = VTY_NORMAL;
  1458. vty->lines = -1;
  1459. vty->iac = 0;
  1460. vty->iac_sb_in_progress = 0;
  1461. vty->sb_len = 0;
  1462. return vty;
  1463. }
  1464. /* Create new vty structure. */
  1465. static struct vty *
  1466. vty_create (int vty_sock, union sockunion *su)
  1467. {
  1468. char buf[SU_ADDRSTRLEN];
  1469. struct vty *vty;
  1470. sockunion2str(su, buf, SU_ADDRSTRLEN);
  1471. /* Allocate new vty structure and set up default values. */
  1472. vty = vty_new_init (vty_sock);
  1473. /* configurable parameters not part of basic init */
  1474. vty->v_timeout = vty_timeout_val;
  1475. strcpy (vty->address, buf);
  1476. if (no_password_check)
  1477. {
  1478. if (restricted_mode)
  1479. vty->node = RESTRICTED_NODE;
  1480. else if (host.advanced)
  1481. vty->node = ENABLE_NODE;
  1482. else
  1483. vty->node = VIEW_NODE;
  1484. }
  1485. if (host.lines >= 0)
  1486. vty->lines = host.lines;
  1487. if (! no_password_check)
  1488. {
  1489. /* Vty is not available if password isn't set. */
  1490. if (host.password == NULL && host.password_encrypt == NULL)
  1491. {
  1492. vty_out (vty, "Vty password is not set.%s", VTY_NEWLINE);
  1493. vty->status = VTY_CLOSE;
  1494. vty_close (vty);
  1495. return NULL;
  1496. }
  1497. }
  1498. /* Say hello to the world. */
  1499. vty_hello (vty);
  1500. if (! no_password_check)
  1501. vty_out (vty, "%sUser Access Verification%s%s", VTY_NEWLINE, VTY_NEWLINE, VTY_NEWLINE);
  1502. /* Setting up terminal. */
  1503. vty_will_echo (vty);
  1504. vty_will_suppress_go_ahead (vty);
  1505. vty_dont_linemode (vty);
  1506. vty_do_window_size (vty);
  1507. /* vty_dont_lflow_ahead (vty); */
  1508. vty_prompt (vty);
  1509. /* Add read/write thread. */
  1510. vty_event (VTY_WRITE, vty_sock, vty);
  1511. vty_event (VTY_READ, vty_sock, vty);
  1512. return vty;
  1513. }
  1514. /* create vty for stdio */
  1515. static struct termios stdio_orig_termios;
  1516. static struct vty *stdio_vty = NULL;
  1517. static void (*stdio_vty_atclose)(void);
  1518. static void
  1519. vty_stdio_reset (void)
  1520. {
  1521. if (stdio_vty)
  1522. {
  1523. tcsetattr (0, TCSANOW, &stdio_orig_termios);
  1524. stdio_vty = NULL;
  1525. if (stdio_vty_atclose)
  1526. stdio_vty_atclose ();
  1527. stdio_vty_atclose = NULL;
  1528. }
  1529. }
  1530. struct vty *
  1531. vty_stdio (void (*atclose)())
  1532. {
  1533. struct vty *vty;
  1534. struct termios termios;
  1535. /* refuse creating two vtys on stdio */
  1536. if (stdio_vty)
  1537. return NULL;
  1538. vty = stdio_vty = vty_new_init (0);
  1539. stdio_vty_atclose = atclose;
  1540. vty->wfd = 1;
  1541. /* always have stdio vty in a known _unchangeable_ state, don't want config
  1542. * to have any effect here to make sure scripting this works as intended */
  1543. vty->node = ENABLE_NODE;
  1544. vty->v_timeout = 0;
  1545. strcpy (vty->address, "console");
  1546. if (!tcgetattr (0, &stdio_orig_termios))
  1547. {
  1548. termios = stdio_orig_termios;
  1549. termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
  1550. | INLCR | IGNCR | ICRNL | IXON);
  1551. termios.c_oflag &= ~OPOST;
  1552. termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  1553. termios.c_cflag &= ~(CSIZE | PARENB);
  1554. termios.c_cflag |= CS8;
  1555. tcsetattr (0, TCSANOW, &termios);
  1556. }
  1557. vty_prompt (vty);
  1558. /* Add read/write thread. */
  1559. vty_event (VTY_WRITE, 1, vty);
  1560. vty_event (VTY_READ, 0, vty);
  1561. return vty;
  1562. }
  1563. /* Accept connection from the network. */
  1564. static int
  1565. vty_accept (struct thread *thread)
  1566. {
  1567. int vty_sock;
  1568. union sockunion su;
  1569. int ret;
  1570. unsigned int on;
  1571. int accept_sock;
  1572. struct prefix p;
  1573. struct access_list *acl = NULL;
  1574. char buf[SU_ADDRSTRLEN];
  1575. accept_sock = THREAD_FD (thread);
  1576. /* We continue hearing vty socket. */
  1577. vty_event (VTY_SERV, accept_sock, NULL);
  1578. memset (&su, 0, sizeof (union sockunion));
  1579. /* We can handle IPv4 or IPv6 socket. */
  1580. vty_sock = sockunion_accept (accept_sock, &su);
  1581. if (vty_sock < 0)
  1582. {
  1583. zlog_warn ("can't accept vty socket : %s", safe_strerror (errno));
  1584. return -1;
  1585. }
  1586. set_nonblocking(vty_sock);
  1587. sockunion2hostprefix (&su, &p);
  1588. /* VTY's accesslist apply. */
  1589. if (p.family == AF_INET && vty_accesslist_name)
  1590. {
  1591. if ((acl = access_list_lookup (AFI_IP, vty_accesslist_name)) &&
  1592. (access_list_apply (acl, &p) == FILTER_DENY))
  1593. {
  1594. zlog (NULL, LOG_INFO, "Vty connection refused from %s",
  1595. sockunion2str (&su, buf, SU_ADDRSTRLEN));
  1596. close (vty_sock);
  1597. /* continue accepting connections */
  1598. vty_event (VTY_SERV, accept_sock, NULL);
  1599. return 0;
  1600. }
  1601. }
  1602. #ifdef HAVE_IPV6
  1603. /* VTY's ipv6 accesslist apply. */
  1604. if (p.family == AF_INET6 && vty_ipv6_accesslist_name)
  1605. {
  1606. if ((acl = access_list_lookup (AFI_IP6, vty_ipv6_accesslist_name)) &&
  1607. (access_list_apply (acl, &p) == FILTER_DENY))
  1608. {
  1609. zlog (NULL, LOG_INFO, "Vty connection refused from %s",
  1610. sockunion2str (&su, buf, SU_ADDRSTRLEN));
  1611. close (vty_sock);
  1612. /* continue accepting connections */
  1613. vty_event (VTY_SERV, accept_sock, NULL);
  1614. return 0;
  1615. }
  1616. }
  1617. #endif /* HAVE_IPV6 */
  1618. on = 1;
  1619. ret = setsockopt (vty_sock, IPPROTO_TCP, TCP_NODELAY,
  1620. (char *) &on, sizeof (on));
  1621. if (ret < 0)
  1622. zlog (NULL, LOG_INFO, "can't set sockopt to vty_sock : %s",
  1623. safe_strerror (errno));
  1624. zlog (NULL, LOG_INFO, "Vty connection from %s",
  1625. sockunion2str (&su, buf, SU_ADDRSTRLEN));
  1626. vty_create (vty_sock, &su);
  1627. return 0;
  1628. }
  1629. #ifdef HAVE_IPV6
  1630. static void
  1631. vty_serv_sock_addrinfo (const char *hostname, unsigned short port)
  1632. {
  1633. int ret;
  1634. struct addrinfo req;
  1635. struct addrinfo *ainfo;
  1636. struct addrinfo *ainfo_save;
  1637. int sock;
  1638. char port_str[BUFSIZ];
  1639. memset (&req, 0, sizeof (struct addrinfo));
  1640. req.ai_flags = AI_PASSIVE;
  1641. req.ai_family = AF_UNSPEC;
  1642. req.ai_socktype = SOCK_STREAM;
  1643. sprintf (port_str, "%d", port);
  1644. port_str[sizeof (port_str) - 1] = '\0';
  1645. ret = getaddrinfo (hostname, port_str, &req, &ainfo);
  1646. if (ret != 0)
  1647. {
  1648. fprintf (stderr, "getaddrinfo failed: %s\n", gai_strerror (ret));
  1649. exit (1);
  1650. }
  1651. ainfo_save = ainfo;
  1652. do
  1653. {
  1654. if (ainfo->ai_family != AF_INET
  1655. #ifdef HAVE_IPV6
  1656. && ainfo->ai_family != AF_INET6
  1657. #endif /* HAVE_IPV6 */
  1658. )
  1659. continue;
  1660. sock = socket (ainfo->ai_family, ainfo->ai_socktype, ainfo->ai_protocol);
  1661. if (sock < 0)
  1662. continue;
  1663. sockopt_v6only (ainfo->ai_family, sock);
  1664. sockopt_reuseaddr (sock);
  1665. sockopt_reuseport (sock);
  1666. ret = bind (sock, ainfo->ai_addr, ainfo->ai_addrlen);
  1667. if (ret < 0)
  1668. {
  1669. close (sock); /* Avoid sd leak. */
  1670. continue;
  1671. }
  1672. ret = listen (sock, 3);
  1673. if (ret < 0)
  1674. {
  1675. close (sock); /* Avoid sd leak. */
  1676. continue;
  1677. }
  1678. vty_event (VTY_SERV, sock, NULL);
  1679. }
  1680. while ((ainfo = ainfo->ai_next) != NULL);
  1681. freeaddrinfo (ainfo_save);
  1682. }
  1683. #else /* HAVE_IPV6 */
  1684. /* Make vty server socket. */
  1685. static void
  1686. vty_serv_sock_family (const char* addr, unsigned short port, int family)
  1687. {
  1688. int ret;
  1689. union sockunion su;
  1690. int accept_sock;
  1691. void* naddr=NULL;
  1692. memset (&su, 0, sizeof (union sockunion));
  1693. su.sa.sa_family = family;
  1694. if(addr)
  1695. switch(family)
  1696. {
  1697. case AF_INET:
  1698. naddr=&su.sin.sin_addr;
  1699. break;
  1700. #ifdef HAVE_IPV6
  1701. case AF_INET6:
  1702. naddr=&su.sin6.sin6_addr;
  1703. break;
  1704. #endif
  1705. }
  1706. if(naddr)
  1707. switch(inet_pton(family,addr,naddr))
  1708. {
  1709. case -1:
  1710. zlog_err("bad address %s",addr);
  1711. naddr=NULL;
  1712. break;
  1713. case 0:
  1714. zlog_err("error translating address %s: %s",addr,safe_strerror(errno));
  1715. naddr=NULL;
  1716. }
  1717. /* Make new socket. */
  1718. accept_sock = sockunion_stream_socket (&su);
  1719. if (accept_sock < 0)
  1720. return;
  1721. /* This is server, so reuse address. */
  1722. sockopt_reuseaddr (accept_sock);
  1723. sockopt_reuseport (accept_sock);
  1724. /* Bind socket to universal address and given port. */
  1725. ret = sockunion_bind (accept_sock, &su, port, naddr);
  1726. if (ret < 0)
  1727. {
  1728. zlog_warn("can't bind socket");
  1729. close (accept_sock); /* Avoid sd leak. */
  1730. return;
  1731. }
  1732. /* Listen socket under queue 3. */
  1733. ret = listen (accept_sock, 3);
  1734. if (ret < 0)
  1735. {
  1736. zlog (NULL, LOG_WARNING, "can't listen socket");
  1737. close (accept_sock); /* Avoid sd leak. */
  1738. return;
  1739. }
  1740. /* Add vty server event. */
  1741. vty_event (VTY_SERV, accept_sock, NULL);
  1742. }
  1743. #endif /* HAVE_IPV6 */
  1744. #ifdef VTYSH
  1745. /* For sockaddr_un. */
  1746. #include <sys/un.h>
  1747. /* VTY shell UNIX domain socket. */
  1748. static void
  1749. vty_serv_un (const char *path)
  1750. {
  1751. int ret;
  1752. int sock, len;
  1753. struct sockaddr_un serv;
  1754. mode_t old_mask;
  1755. struct zprivs_ids_t ids;
  1756. /* First of all, unlink existing socket */
  1757. unlink (path);
  1758. /* Set umask */
  1759. old_mask = umask (0007);
  1760. /* Make UNIX domain socket. */
  1761. sock = socket (AF_UNIX, SOCK_STREAM, 0);
  1762. if (sock < 0)
  1763. {
  1764. zlog_err("Cannot create unix stream socket: %s", safe_strerror(errno));
  1765. return;
  1766. }
  1767. /* Make server socket. */
  1768. memset (&serv, 0, sizeof (struct sockaddr_un));
  1769. serv.sun_family = AF_UNIX;
  1770. strncpy (serv.sun_path, path, strlen (path));
  1771. #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN
  1772. len = serv.sun_len = SUN_LEN(&serv);
  1773. #else
  1774. len = sizeof (serv.sun_family) + strlen (serv.sun_path);
  1775. #endif /* HAVE_STRUCT_SOCKADDR_UN_SUN_LEN */
  1776. ret = bind (sock, (struct sockaddr *) &serv, len);
  1777. if (ret < 0)
  1778. {
  1779. zlog_err("Cannot bind path %s: %s", path, safe_strerror(errno));
  1780. close (sock); /* Avoid sd leak. */
  1781. return;
  1782. }
  1783. ret = listen (sock, 5);
  1784. if (ret < 0)
  1785. {
  1786. zlog_err("listen(fd %d) failed: %s", sock, safe_strerror(errno));
  1787. close (sock); /* Avoid sd leak. */
  1788. return;
  1789. }
  1790. umask (old_mask);
  1791. zprivs_get_ids(&ids);
  1792. if (ids.gid_vty > 0)
  1793. {
  1794. /* set group of socket */
  1795. if ( chown (path, -1, ids.gid_vty) )
  1796. {
  1797. zlog_err ("vty_serv_un: could chown socket, %s",
  1798. safe_strerror (errno) );
  1799. }
  1800. }
  1801. vty_event (VTYSH_SERV, sock, NULL);
  1802. }
  1803. /* #define VTYSH_DEBUG 1 */
  1804. static int
  1805. vtysh_accept (struct thread *thread)
  1806. {
  1807. int accept_sock;
  1808. int sock;
  1809. int client_len;
  1810. struct sockaddr_un client;
  1811. struct vty *vty;
  1812. accept_sock = THREAD_FD (thread);
  1813. vty_event (VTYSH_SERV, accept_sock, NULL);
  1814. memset (&client, 0, sizeof (struct sockaddr_un));
  1815. client_len = sizeof (struct sockaddr_un);
  1816. sock = accept (accept_sock, (struct sockaddr *) &client,
  1817. (socklen_t *) &client_len);
  1818. if (sock < 0)
  1819. {
  1820. zlog_warn ("can't accept vty socket : %s", safe_strerror (errno));
  1821. return -1;
  1822. }
  1823. if (set_nonblocking(sock) < 0)
  1824. {
  1825. zlog_warn ("vtysh_accept: could not set vty socket %d to non-blocking,"
  1826. " %s, closing", sock, safe_strerror (errno));
  1827. close (sock);
  1828. return -1;
  1829. }
  1830. #ifdef VTYSH_DEBUG
  1831. printf ("VTY shell accept\n");
  1832. #endif /* VTYSH_DEBUG */
  1833. vty = vty_new ();
  1834. vty->fd = sock;
  1835. vty->wfd = sock;
  1836. vty->type = VTY_SHELL_SERV;
  1837. vty->node = VIEW_NODE;
  1838. vty_event (VTYSH_READ, sock, vty);
  1839. return 0;
  1840. }
  1841. static int
  1842. vtysh_flush(struct vty *vty)
  1843. {
  1844. switch (buffer_flush_available(vty->obuf, vty->wfd))
  1845. {
  1846. case BUFFER_PENDING:
  1847. vty_event(VTYSH_WRITE, vty->wfd, vty);
  1848. break;
  1849. case BUFFER_ERROR:
  1850. vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
  1851. zlog_warn("%s: write error to fd %d, closing", __func__, vty->fd);
  1852. buffer_reset(vty->obuf);
  1853. vty_close(vty);
  1854. return -1;
  1855. break;
  1856. case BUFFER_EMPTY:
  1857. break;
  1858. }
  1859. return 0;
  1860. }
  1861. static int
  1862. vtysh_read (struct thread *thread)
  1863. {
  1864. int ret;
  1865. int sock;
  1866. int nbytes;
  1867. struct vty *vty;
  1868. unsigned char buf[VTY_READ_BUFSIZ];
  1869. unsigned char *p;
  1870. u_char header[4] = {0, 0, 0, 0};
  1871. sock = THREAD_FD (thread);
  1872. vty = THREAD_ARG (thread);
  1873. vty->t_read = NULL;
  1874. if ((nbytes = read (sock, buf, VTY_READ_BUFSIZ)) <= 0)
  1875. {
  1876. if (nbytes < 0)
  1877. {
  1878. if (ERRNO_IO_RETRY(errno))
  1879. {
  1880. vty_event (VTYSH_READ, sock, vty);
  1881. return 0;
  1882. }
  1883. vty->monitor = 0; /* disable monitoring to avoid infinite recursion */
  1884. zlog_warn("%s: read failed on vtysh client fd %d, closing: %s",
  1885. __func__, sock, safe_strerror(errno));
  1886. }
  1887. buffer_reset(vty->obuf);
  1888. vty_close (vty);
  1889. #ifdef VTYSH_DEBUG
  1890. printf ("close vtysh\n");
  1891. #endif /* VTYSH_DEBUG */
  1892. return 0;
  1893. }
  1894. #ifdef VTYSH_DEBUG
  1895. printf ("line: %.*s\n", nbytes, buf);
  1896. #endif /* VTYSH_DEBUG */
  1897. if (vty->length + nbytes > VTY_BUFSIZ)
  1898. {
  1899. /* Clear command line buffer. */
  1900. vty->cp = vty->length = 0;
  1901. vty_clear_buf (vty);
  1902. vty_out (vty, "%% Command is too long.%s", VTY_NEWLINE);
  1903. goto out;
  1904. }
  1905. for (p = buf; p < buf+nbytes; p++)
  1906. {
  1907. vty->buf[vty->length++] = *p;
  1908. if (*p == '\0')
  1909. {
  1910. /* Pass this line to parser. */
  1911. ret = vty_execute (vty);
  1912. /* Note that vty_execute clears the command buffer and resets
  1913. vty->length to 0. */
  1914. /* Return result. */
  1915. #ifdef VTYSH_DEBUG
  1916. printf ("result: %d\n", ret);
  1917. printf ("vtysh node: %d\n", vty->node);
  1918. #endif /* VTYSH_DEBUG */
  1919. header[3] = ret;
  1920. buffer_put(vty->obuf, header, 4);
  1921. if (!vty->t_write && (vtysh_flush(vty) < 0))
  1922. /* Try to flush results; exit if a write error occurs. */
  1923. return 0;
  1924. }
  1925. }
  1926. out:
  1927. vty_event (VTYSH_READ, sock, vty);
  1928. return 0;
  1929. }
  1930. static int
  1931. vtysh_write (struct thread *thread)
  1932. {
  1933. struct vty *vty = THREAD_ARG (thread);
  1934. vty->t_write = NULL;
  1935. vtysh_flush(vty);
  1936. return 0;
  1937. }
  1938. #endif /* VTYSH */
  1939. /* Determine address family to bind. */
  1940. void
  1941. vty_serv_sock (const char *addr, unsigned short port, const char *path)
  1942. {
  1943. /* If port is set to 0, do not listen on TCP/IP at all! */
  1944. if (port)
  1945. {
  1946. #ifdef HAVE_IPV6
  1947. vty_serv_sock_addrinfo (addr, port);
  1948. #else /* ! HAVE_IPV6 */
  1949. vty_serv_sock_family (addr,port, AF_INET);
  1950. #endif /* HAVE_IPV6 */
  1951. }
  1952. #ifdef VTYSH
  1953. vty_serv_un (path);
  1954. #endif /* VTYSH */
  1955. }
  1956. /* Close vty interface. Warning: call this only from functions that
  1957. will be careful not to access the vty afterwards (since it has
  1958. now been freed). This is safest from top-level functions (called
  1959. directly by the thread dispatcher). */
  1960. void
  1961. vty_close (struct vty *vty)
  1962. {
  1963. int i;
  1964. /* Cancel threads.*/
  1965. if (vty->t_read)
  1966. thread_cancel (vty->t_read);
  1967. if (vty->t_write)
  1968. thread_cancel (vty->t_write);
  1969. if (vty->t_timeout)
  1970. thread_cancel (vty->t_timeout);
  1971. /* Flush buffer. */
  1972. buffer_flush_all (vty->obuf, vty->wfd);
  1973. /* Free input buffer. */
  1974. buffer_free (vty->obuf);
  1975. /* Free command history. */
  1976. for (i = 0; i < VTY_MAXHIST; i++)
  1977. if (vty->hist[i])
  1978. XFREE (MTYPE_VTY_HIST, vty->hist[i]);
  1979. /* Unset vector. */
  1980. vector_unset (vtyvec, vty->fd);
  1981. /* Close socket. */
  1982. if (vty->fd > 0)
  1983. close (vty->fd);
  1984. else
  1985. vty_stdio_reset ();
  1986. if (vty->buf)
  1987. XFREE (MTYPE_VTY, vty->buf);
  1988. /* Check configure. */
  1989. vty_config_unlock (vty);
  1990. /* OK free vty. */
  1991. XFREE (MTYPE_VTY, vty);
  1992. }
  1993. /* When time out occur output message then close connection. */
  1994. static int
  1995. vty_timeout (struct thread *thread)
  1996. {
  1997. struct vty *vty;
  1998. vty = THREAD_ARG (thread);
  1999. vty->t_timeout = NULL;
  2000. vty->v_timeout = 0;
  2001. /* Clear buffer*/
  2002. buffer_reset (vty->obuf);
  2003. vty_out (vty, "%sVty connection is timed out.%s", VTY_NEWLINE, VTY_NEWLINE);
  2004. /* Close connection. */
  2005. vty->status = VTY_CLOSE;
  2006. vty_close (vty);
  2007. return 0;
  2008. }
  2009. /* Read up configuration file from file_name. */
  2010. static void
  2011. vty_read_file (FILE *confp)
  2012. {
  2013. int ret;
  2014. struct vty *vty;
  2015. unsigned int line_num = 0;
  2016. vty = vty_new ();
  2017. vty->wfd = dup(STDERR_FILENO); /* vty_close() will close this */
  2018. if (vty->wfd < 0)
  2019. {
  2020. /* Fine, we couldn't make a new fd. vty_close doesn't close stdout. */
  2021. vty->wfd = STDOUT_FILENO;
  2022. }
  2023. vty->fd = STDIN_FILENO;
  2024. vty->type = VTY_FILE;
  2025. vty->node = CONFIG_NODE;
  2026. /* Execute configuration file */
  2027. ret = config_from_file (vty, confp, &line_num);
  2028. /* Flush any previous errors before printing messages below */
  2029. buffer_flush_all (vty->obuf, vty->fd);
  2030. if ( !((ret == CMD_SUCCESS) || (ret == CMD_ERR_NOTHING_TODO)) )
  2031. {
  2032. switch (ret)
  2033. {
  2034. case CMD_ERR_AMBIGUOUS:
  2035. fprintf (stderr, "*** Error reading config: Ambiguous command.\n");
  2036. break;
  2037. case CMD_ERR_NO_MATCH:
  2038. fprintf (stderr, "*** Error reading config: There is no such command.\n");
  2039. break;
  2040. }
  2041. fprintf (stderr, "*** Error occured processing line %u, below:\n%s\n",
  2042. line_num, vty->buf);
  2043. vty_close (vty);
  2044. exit (1);
  2045. }
  2046. vty_close (vty);
  2047. }
  2048. static FILE *
  2049. vty_use_backup_config (char *fullpath)
  2050. {
  2051. char *fullpath_sav, *fullpath_tmp;
  2052. FILE *ret = NULL;
  2053. struct stat buf;
  2054. int tmp, sav;
  2055. int c;
  2056. char buffer[512];
  2057. fullpath_sav = malloc (strlen (fullpath) + strlen (CONF_BACKUP_EXT) + 1);
  2058. strcpy (fullpath_sav, fullpath);
  2059. strcat (fullpath_sav, CONF_BACKUP_EXT);
  2060. if (stat (fullpath_sav, &buf) == -1)
  2061. {
  2062. free (fullpath_sav);
  2063. return NULL;
  2064. }
  2065. fullpath_tmp = malloc (strlen (fullpath) + 8);
  2066. sprintf (fullpath_tmp, "%s.XXXXXX", fullpath);
  2067. /* Open file to configuration write. */
  2068. tmp = mkstemp (fullpath_tmp);
  2069. if (tmp < 0)
  2070. {
  2071. free (fullpath_sav);
  2072. free (fullpath_tmp);
  2073. return NULL;
  2074. }
  2075. sav = open (fullpath_sav, O_RDONLY);
  2076. if (sav < 0)
  2077. {
  2078. unlink (fullpath_tmp);
  2079. free (fullpath_sav);
  2080. free (fullpath_tmp);
  2081. return NULL;
  2082. }
  2083. while((c = read (sav, buffer, 512)) > 0)
  2084. write (tmp, buffer, c);
  2085. close (sav);
  2086. close (tmp);
  2087. if (chmod(fullpath_tmp, CONFIGFILE_MASK) != 0)
  2088. {
  2089. unlink (fullpath_tmp);
  2090. free (fullpath_sav);
  2091. free (fullpath_tmp);
  2092. return NULL;
  2093. }
  2094. if (link (fullpath_tmp, fullpath) == 0)
  2095. ret = fopen (fullpath, "r");
  2096. unlink (fullpath_tmp);
  2097. free (fullpath_sav);
  2098. free (fullpath_tmp);
  2099. return ret;
  2100. }
  2101. /* Read up configuration file from file_name. */
  2102. void
  2103. vty_read_config (char *config_file,
  2104. char *config_default_dir)
  2105. {
  2106. char cwd[MAXPATHLEN];
  2107. FILE *confp = NULL;
  2108. char *fullpath;
  2109. char *tmp = NULL;
  2110. /* If -f flag specified. */
  2111. if (config_file != NULL)
  2112. {
  2113. if (! IS_DIRECTORY_SEP (config_file[0]))
  2114. {
  2115. getcwd (cwd, MAXPATHLEN);
  2116. tmp = XMALLOC (MTYPE_TMP,
  2117. strlen (cwd) + strlen (config_file) + 2);
  2118. sprintf (tmp, "%s/%s", cwd, config_file);
  2119. fullpath = tmp;
  2120. }
  2121. else
  2122. fullpath = config_file;
  2123. confp = fopen (fullpath, "r");
  2124. if (confp == NULL)
  2125. {
  2126. fprintf (stderr, "%s: failed to open configuration file %s: %s\n",
  2127. __func__, fullpath, safe_strerror (errno));
  2128. confp = vty_use_backup_config (fullpath);
  2129. if (confp)
  2130. fprintf (stderr, "WARNING: using backup configuration file!\n");
  2131. else
  2132. {
  2133. fprintf (stderr, "can't open configuration file [%s]\n",
  2134. config_file);
  2135. exit(1);
  2136. }
  2137. }
  2138. }
  2139. else
  2140. {
  2141. #ifdef VTYSH
  2142. int ret;
  2143. struct stat conf_stat;
  2144. /* !!!!PLEASE LEAVE!!!!
  2145. * This is NEEDED for use with vtysh -b, or else you can get
  2146. * a real configuration food fight with a lot garbage in the
  2147. * merged configuration file it creates coming from the per
  2148. * daemon configuration files. This also allows the daemons
  2149. * to start if there default configuration file is not
  2150. * present or ignore them, as needed when using vtysh -b to
  2151. * configure the daemons at boot - MAG
  2152. */
  2153. /* Stat for vtysh Zebra.conf, if found startup and wait for
  2154. * boot configuration
  2155. */
  2156. if ( strstr(config_default_dir, "vtysh") == NULL)
  2157. {
  2158. ret = stat (integrate_default, &conf_stat);
  2159. if (ret >= 0)
  2160. return;
  2161. }
  2162. #endif /* VTYSH */
  2163. confp = fopen (config_default_dir, "r");
  2164. if (confp == NULL)
  2165. {
  2166. fprintf (stderr, "%s: failed to open configuration file %s: %s\n",
  2167. __func__, config_default_dir, safe_strerror (errno));
  2168. confp = vty_use_backup_config (config_default_dir);
  2169. if (confp)
  2170. {
  2171. fprintf (stderr, "WARNING: using backup configuration file!\n");
  2172. fullpath = config_default_dir;
  2173. }
  2174. else
  2175. {
  2176. fprintf (stderr, "can't open configuration file [%s]\n",
  2177. config_default_dir);
  2178. exit (1);
  2179. }
  2180. }
  2181. else
  2182. fullpath = config_default_dir;
  2183. }
  2184. vty_read_file (confp);
  2185. fclose (confp);
  2186. host_config_set (fullpath);
  2187. if (tmp)
  2188. XFREE (MTYPE_TMP, fullpath);
  2189. }
  2190. /* Small utility function which output log to the VTY. */
  2191. void
  2192. vty_log (const char *level, const char *proto_str,
  2193. const char *format, struct timestamp_control *ctl, va_list va)
  2194. {
  2195. unsigned int i;
  2196. struct vty *vty;
  2197. if (!vtyvec)
  2198. return;
  2199. for (i = 0; i < vector_active (vtyvec); i++)
  2200. if ((vty = vector_slot (vtyvec, i)) != NULL)
  2201. if (vty->monitor)
  2202. {
  2203. va_list ac;
  2204. va_copy(ac, va);
  2205. vty_log_out (vty, level, proto_str, format, ctl, ac);
  2206. va_end(ac);
  2207. }
  2208. }
  2209. /* Async-signal-safe version of vty_log for fixed strings. */
  2210. void
  2211. vty_log_fixed (char *buf, size_t len)
  2212. {
  2213. unsigned int i;
  2214. struct iovec iov[2];
  2215. /* vty may not have been initialised */
  2216. if (!vtyvec)
  2217. return;
  2218. iov[0].iov_base = buf;
  2219. iov[0].iov_len = len;
  2220. iov[1].iov_base = (void *)"\r\n";
  2221. iov[1].iov_len = 2;
  2222. for (i = 0; i < vector_active (vtyvec); i++)
  2223. {
  2224. struct vty *vty;
  2225. if (((vty = vector_slot (vtyvec, i)) != NULL) && vty->monitor)
  2226. /* N.B. We don't care about the return code, since process is
  2227. most likely just about to die anyway. */
  2228. writev(vty->wfd, iov, 2);
  2229. }
  2230. }
  2231. int
  2232. vty_config_lock (struct vty *vty)
  2233. {
  2234. if (vty_config == 0)
  2235. {
  2236. vty->config = 1;
  2237. vty_config = 1;
  2238. }
  2239. return vty->config;
  2240. }
  2241. int
  2242. vty_config_unlock (struct vty *vty)
  2243. {
  2244. if (vty_config == 1 && vty->config == 1)
  2245. {
  2246. vty->config = 0;
  2247. vty_config = 0;
  2248. }
  2249. return vty->config;
  2250. }
  2251. /* Master of the threads. */
  2252. static struct thread_master *vty_master;
  2253. static void
  2254. vty_event (enum event event, int sock, struct vty *vty)
  2255. {
  2256. struct thread *vty_serv_thread;
  2257. switch (event)
  2258. {
  2259. case VTY_SERV:
  2260. vty_serv_thread = thread_add_read (vty_master, vty_accept, vty, sock);
  2261. vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
  2262. break;
  2263. #ifdef VTYSH
  2264. case VTYSH_SERV:
  2265. vty_serv_thread = thread_add_read (vty_master, vtysh_accept, vty, sock);
  2266. vector_set_index (Vvty_serv_thread, sock, vty_serv_thread);
  2267. break;
  2268. case VTYSH_READ:
  2269. vty->t_read = thread_add_read (vty_master, vtysh_read, vty, sock);
  2270. break;
  2271. case VTYSH_WRITE:
  2272. vty->t_write = thread_add_write (vty_master, vtysh_write, vty, sock);
  2273. break;
  2274. #endif /* VTYSH */
  2275. case VTY_READ:
  2276. vty->t_read = thread_add_read (vty_master, vty_read, vty, sock);
  2277. /* Time out treatment. */
  2278. if (vty->v_timeout)
  2279. {
  2280. if (vty->t_timeout)
  2281. thread_cancel (vty->t_timeout);
  2282. vty->t_timeout =
  2283. thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
  2284. }
  2285. break;
  2286. case VTY_WRITE:
  2287. if (! vty->t_write)
  2288. vty->t_write = thread_add_write (vty_master, vty_flush, vty, sock);
  2289. break;
  2290. case VTY_TIMEOUT_RESET:
  2291. if (vty->t_timeout)
  2292. {
  2293. thread_cancel (vty->t_timeout);
  2294. vty->t_timeout = NULL;
  2295. }
  2296. if (vty->v_timeout)
  2297. {
  2298. vty->t_timeout =
  2299. thread_add_timer (vty_master, vty_timeout, vty, vty->v_timeout);
  2300. }
  2301. break;
  2302. }
  2303. }
  2304. DEFUN (who,
  2305. who_cmd,
  2306. "who",
  2307. "Display who is on vty\n")
  2308. {
  2309. unsigned int i;
  2310. struct vty *v;
  2311. for (i = 0; i < vector_active (vtyvec); i++)
  2312. if ((v = vector_slot (vtyvec, i)) != NULL)
  2313. vty_out (vty, "%svty[%d] connected from %s.%s",
  2314. v->config ? "*" : " ",
  2315. i, v->address, VTY_NEWLINE);
  2316. return CMD_SUCCESS;
  2317. }
  2318. /* Move to vty configuration mode. */
  2319. DEFUN (line_vty,
  2320. line_vty_cmd,
  2321. "line vty",
  2322. "Configure a terminal line\n"
  2323. "Virtual terminal\n")
  2324. {
  2325. vty->node = VTY_NODE;
  2326. return CMD_SUCCESS;
  2327. }
  2328. /* Set time out value. */
  2329. static int
  2330. exec_timeout (struct vty *vty, const char *min_str, const char *sec_str)
  2331. {
  2332. unsigned long timeout = 0;
  2333. /* min_str and sec_str are already checked by parser. So it must be
  2334. all digit string. */
  2335. if (min_str)
  2336. {
  2337. timeout = strtol (min_str, NULL, 10);
  2338. timeout *= 60;
  2339. }
  2340. if (sec_str)
  2341. timeout += strtol (sec_str, NULL, 10);
  2342. vty_timeout_val = timeout;
  2343. vty->v_timeout = timeout;
  2344. vty_event (VTY_TIMEOUT_RESET, 0, vty);
  2345. return CMD_SUCCESS;
  2346. }
  2347. DEFUN (exec_timeout_min,
  2348. exec_timeout_min_cmd,
  2349. "exec-timeout <0-35791>",
  2350. "Set timeout value\n"
  2351. "Timeout value in minutes\n")
  2352. {
  2353. return exec_timeout (vty, argv[0], NULL);
  2354. }
  2355. DEFUN (exec_timeout_sec,
  2356. exec_timeout_sec_cmd,
  2357. "exec-timeout <0-35791> <0-2147483>",
  2358. "Set the EXEC timeout\n"
  2359. "Timeout in minutes\n"
  2360. "Timeout in seconds\n")
  2361. {
  2362. return exec_timeout (vty, argv[0], argv[1]);
  2363. }
  2364. DEFUN (no_exec_timeout,
  2365. no_exec_timeout_cmd,
  2366. "no exec-timeout",
  2367. NO_STR
  2368. "Set the EXEC timeout\n")
  2369. {
  2370. return exec_timeout (vty, NULL, NULL);
  2371. }
  2372. /* Set vty access class. */
  2373. DEFUN (vty_access_class,
  2374. vty_access_class_cmd,
  2375. "access-class WORD",
  2376. "Filter connections based on an IP access list\n"
  2377. "IP access list\n")
  2378. {
  2379. if (vty_accesslist_name)
  2380. XFREE(MTYPE_VTY, vty_accesslist_name);
  2381. vty_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
  2382. return CMD_SUCCESS;
  2383. }
  2384. /* Clear vty access class. */
  2385. DEFUN (no_vty_access_class,
  2386. no_vty_access_class_cmd,
  2387. "no access-class [WORD]",
  2388. NO_STR
  2389. "Filter connections based on an IP access list\n"
  2390. "IP access list\n")
  2391. {
  2392. if (! vty_accesslist_name || (argc && strcmp(vty_accesslist_name, argv[0])))
  2393. {
  2394. vty_out (vty, "Access-class is not currently applied to vty%s",
  2395. VTY_NEWLINE);
  2396. return CMD_WARNING;
  2397. }
  2398. XFREE(MTYPE_VTY, vty_accesslist_name);
  2399. vty_accesslist_name = NULL;
  2400. return CMD_SUCCESS;
  2401. }
  2402. #ifdef HAVE_IPV6
  2403. /* Set vty access class. */
  2404. DEFUN (vty_ipv6_access_class,
  2405. vty_ipv6_access_class_cmd,
  2406. "ipv6 access-class WORD",
  2407. IPV6_STR
  2408. "Filter connections based on an IP access list\n"
  2409. "IPv6 access list\n")
  2410. {
  2411. if (vty_ipv6_accesslist_name)
  2412. XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
  2413. vty_ipv6_accesslist_name = XSTRDUP(MTYPE_VTY, argv[0]);
  2414. return CMD_SUCCESS;
  2415. }
  2416. /* Clear vty access class. */
  2417. DEFUN (no_vty_ipv6_access_class,
  2418. no_vty_ipv6_access_class_cmd,
  2419. "no ipv6 access-class [WORD]",
  2420. NO_STR
  2421. IPV6_STR
  2422. "Filter connections based on an IP access list\n"
  2423. "IPv6 access list\n")
  2424. {
  2425. if (! vty_ipv6_accesslist_name ||
  2426. (argc && strcmp(vty_ipv6_accesslist_name, argv[0])))
  2427. {
  2428. vty_out (vty, "IPv6 access-class is not currently applied to vty%s",
  2429. VTY_NEWLINE);
  2430. return CMD_WARNING;
  2431. }
  2432. XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
  2433. vty_ipv6_accesslist_name = NULL;
  2434. return CMD_SUCCESS;
  2435. }
  2436. #endif /* HAVE_IPV6 */
  2437. /* vty login. */
  2438. DEFUN (vty_login,
  2439. vty_login_cmd,
  2440. "login",
  2441. "Enable password checking\n")
  2442. {
  2443. no_password_check = 0;
  2444. return CMD_SUCCESS;
  2445. }
  2446. DEFUN (no_vty_login,
  2447. no_vty_login_cmd,
  2448. "no login",
  2449. NO_STR
  2450. "Enable password checking\n")
  2451. {
  2452. no_password_check = 1;
  2453. return CMD_SUCCESS;
  2454. }
  2455. /* initial mode. */
  2456. DEFUN (vty_restricted_mode,
  2457. vty_restricted_mode_cmd,
  2458. "anonymous restricted",
  2459. "Restrict view commands available in anonymous, unauthenticated vty\n")
  2460. {
  2461. restricted_mode = 1;
  2462. return CMD_SUCCESS;
  2463. }
  2464. DEFUN (vty_no_restricted_mode,
  2465. vty_no_restricted_mode_cmd,
  2466. "no anonymous restricted",
  2467. NO_STR
  2468. "Enable password checking\n")
  2469. {
  2470. restricted_mode = 0;
  2471. return CMD_SUCCESS;
  2472. }
  2473. DEFUN (service_advanced_vty,
  2474. service_advanced_vty_cmd,
  2475. "service advanced-vty",
  2476. "Set up miscellaneous service\n"
  2477. "Enable advanced mode vty interface\n")
  2478. {
  2479. host.advanced = 1;
  2480. return CMD_SUCCESS;
  2481. }
  2482. DEFUN (no_service_advanced_vty,
  2483. no_service_advanced_vty_cmd,
  2484. "no service advanced-vty",
  2485. NO_STR
  2486. "Set up miscellaneous service\n"
  2487. "Enable advanced mode vty interface\n")
  2488. {
  2489. host.advanced = 0;
  2490. return CMD_SUCCESS;
  2491. }
  2492. DEFUN (terminal_monitor,
  2493. terminal_monitor_cmd,
  2494. "terminal monitor",
  2495. "Set terminal line parameters\n"
  2496. "Copy debug output to the current terminal line\n")
  2497. {
  2498. vty->monitor = 1;
  2499. return CMD_SUCCESS;
  2500. }
  2501. DEFUN (terminal_no_monitor,
  2502. terminal_no_monitor_cmd,
  2503. "terminal no monitor",
  2504. "Set terminal line parameters\n"
  2505. NO_STR
  2506. "Copy debug output to the current terminal line\n")
  2507. {
  2508. vty->monitor = 0;
  2509. return CMD_SUCCESS;
  2510. }
  2511. ALIAS (terminal_no_monitor,
  2512. no_terminal_monitor_cmd,
  2513. "no terminal monitor",
  2514. NO_STR
  2515. "Set terminal line parameters\n"
  2516. "Copy debug output to the current terminal line\n")
  2517. DEFUN (show_history,
  2518. show_history_cmd,
  2519. "show history",
  2520. SHOW_STR
  2521. "Display the session command history\n")
  2522. {
  2523. int index;
  2524. for (index = vty->hindex + 1; index != vty->hindex;)
  2525. {
  2526. if (index == VTY_MAXHIST)
  2527. {
  2528. index = 0;
  2529. continue;
  2530. }
  2531. if (vty->hist[index] != NULL)
  2532. vty_out (vty, " %s%s", vty->hist[index], VTY_NEWLINE);
  2533. index++;
  2534. }
  2535. return CMD_SUCCESS;
  2536. }
  2537. /* vty login. */
  2538. DEFUN (log_commands,
  2539. log_commands_cmd,
  2540. "log commands",
  2541. "Logging control\n"
  2542. "Log all commands (can't be unset without restart)\n")
  2543. {
  2544. do_log_commands = 1;
  2545. return CMD_SUCCESS;
  2546. }
  2547. /* Display current configuration. */
  2548. static int
  2549. vty_config_write (struct vty *vty)
  2550. {
  2551. vty_out (vty, "line vty%s", VTY_NEWLINE);
  2552. if (vty_accesslist_name)
  2553. vty_out (vty, " access-class %s%s",
  2554. vty_accesslist_name, VTY_NEWLINE);
  2555. if (vty_ipv6_accesslist_name)
  2556. vty_out (vty, " ipv6 access-class %s%s",
  2557. vty_ipv6_accesslist_name, VTY_NEWLINE);
  2558. /* exec-timeout */
  2559. if (vty_timeout_val != VTY_TIMEOUT_DEFAULT)
  2560. vty_out (vty, " exec-timeout %ld %ld%s",
  2561. vty_timeout_val / 60,
  2562. vty_timeout_val % 60, VTY_NEWLINE);
  2563. /* login */
  2564. if (no_password_check)
  2565. vty_out (vty, " no login%s", VTY_NEWLINE);
  2566. if (restricted_mode != restricted_mode_default)
  2567. {
  2568. if (restricted_mode_default)
  2569. vty_out (vty, " no anonymous restricted%s", VTY_NEWLINE);
  2570. else
  2571. vty_out (vty, " anonymous restricted%s", VTY_NEWLINE);
  2572. }
  2573. if (do_log_commands)
  2574. vty_out (vty, "log commands%s", VTY_NEWLINE);
  2575. vty_out (vty, "!%s", VTY_NEWLINE);
  2576. return CMD_SUCCESS;
  2577. }
  2578. struct cmd_node vty_node =
  2579. {
  2580. VTY_NODE,
  2581. "%s(config-line)# ",
  2582. 1,
  2583. };
  2584. /* Reset all VTY status. */
  2585. void
  2586. vty_reset ()
  2587. {
  2588. unsigned int i;
  2589. struct vty *vty;
  2590. struct thread *vty_serv_thread;
  2591. for (i = 0; i < vector_active (vtyvec); i++)
  2592. if ((vty = vector_slot (vtyvec, i)) != NULL)
  2593. {
  2594. buffer_reset (vty->obuf);
  2595. vty->status = VTY_CLOSE;
  2596. vty_close (vty);
  2597. }
  2598. for (i = 0; i < vector_active (Vvty_serv_thread); i++)
  2599. if ((vty_serv_thread = vector_slot (Vvty_serv_thread, i)) != NULL)
  2600. {
  2601. thread_cancel (vty_serv_thread);
  2602. vector_slot (Vvty_serv_thread, i) = NULL;
  2603. close (i);
  2604. }
  2605. vty_timeout_val = VTY_TIMEOUT_DEFAULT;
  2606. if (vty_accesslist_name)
  2607. {
  2608. XFREE(MTYPE_VTY, vty_accesslist_name);
  2609. vty_accesslist_name = NULL;
  2610. }
  2611. if (vty_ipv6_accesslist_name)
  2612. {
  2613. XFREE(MTYPE_VTY, vty_ipv6_accesslist_name);
  2614. vty_ipv6_accesslist_name = NULL;
  2615. }
  2616. }
  2617. static void
  2618. vty_save_cwd (void)
  2619. {
  2620. char cwd[MAXPATHLEN];
  2621. char *c;
  2622. c = getcwd (cwd, MAXPATHLEN);
  2623. if (!c)
  2624. {
  2625. chdir (SYSCONFDIR);
  2626. getcwd (cwd, MAXPATHLEN);
  2627. }
  2628. vty_cwd = XMALLOC (MTYPE_TMP, strlen (cwd) + 1);
  2629. strcpy (vty_cwd, cwd);
  2630. }
  2631. char *
  2632. vty_get_cwd ()
  2633. {
  2634. return vty_cwd;
  2635. }
  2636. int
  2637. vty_shell (struct vty *vty)
  2638. {
  2639. return vty->type == VTY_SHELL ? 1 : 0;
  2640. }
  2641. int
  2642. vty_shell_serv (struct vty *vty)
  2643. {
  2644. return vty->type == VTY_SHELL_SERV ? 1 : 0;
  2645. }
  2646. void
  2647. vty_init_vtysh ()
  2648. {
  2649. vtyvec = vector_init (VECTOR_MIN_SIZE);
  2650. }
  2651. /* Install vty's own commands like `who' command. */
  2652. void
  2653. vty_init (struct thread_master *master_thread)
  2654. {
  2655. /* For further configuration read, preserve current directory. */
  2656. vty_save_cwd ();
  2657. vtyvec = vector_init (VECTOR_MIN_SIZE);
  2658. vty_master = master_thread;
  2659. atexit (vty_stdio_reset);
  2660. /* Initilize server thread vector. */
  2661. Vvty_serv_thread = vector_init (VECTOR_MIN_SIZE);
  2662. /* Install bgp top node. */
  2663. install_node (&vty_node, vty_config_write);
  2664. install_element (RESTRICTED_NODE, &who_cmd);
  2665. install_element (RESTRICTED_NODE, &show_history_cmd);
  2666. install_element (VIEW_NODE, &who_cmd);
  2667. install_element (VIEW_NODE, &show_history_cmd);
  2668. install_element (CONFIG_NODE, &line_vty_cmd);
  2669. install_element (CONFIG_NODE, &service_advanced_vty_cmd);
  2670. install_element (CONFIG_NODE, &no_service_advanced_vty_cmd);
  2671. install_element (CONFIG_NODE, &show_history_cmd);
  2672. install_element (CONFIG_NODE, &log_commands_cmd);
  2673. install_element (ENABLE_NODE, &terminal_monitor_cmd);
  2674. install_element (ENABLE_NODE, &terminal_no_monitor_cmd);
  2675. install_element (ENABLE_NODE, &no_terminal_monitor_cmd);
  2676. install_default (VTY_NODE);
  2677. install_element (VTY_NODE, &exec_timeout_min_cmd);
  2678. install_element (VTY_NODE, &exec_timeout_sec_cmd);
  2679. install_element (VTY_NODE, &no_exec_timeout_cmd);
  2680. install_element (VTY_NODE, &vty_access_class_cmd);
  2681. install_element (VTY_NODE, &no_vty_access_class_cmd);
  2682. install_element (VTY_NODE, &vty_login_cmd);
  2683. install_element (VTY_NODE, &no_vty_login_cmd);
  2684. install_element (VTY_NODE, &vty_restricted_mode_cmd);
  2685. install_element (VTY_NODE, &vty_no_restricted_mode_cmd);
  2686. #ifdef HAVE_IPV6
  2687. install_element (VTY_NODE, &vty_ipv6_access_class_cmd);
  2688. install_element (VTY_NODE, &no_vty_ipv6_access_class_cmd);
  2689. #endif /* HAVE_IPV6 */
  2690. }
  2691. void
  2692. vty_terminate (void)
  2693. {
  2694. if (vty_cwd)
  2695. XFREE (MTYPE_TMP, vty_cwd);
  2696. if (vtyvec && Vvty_serv_thread)
  2697. {
  2698. vty_reset ();
  2699. vector_free (vtyvec);
  2700. vector_free (Vvty_serv_thread);
  2701. }
  2702. }