isis_pdu.c 88 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201
  1. /*
  2. * IS-IS Rout(e)ing protocol - isis_pdu.c
  3. * PDU processing
  4. *
  5. * Copyright (C) 2001,2002 Sampo Saaristo
  6. * Tampere University of Technology
  7. * Institute of Communications Engineering
  8. *
  9. * This program is free software; you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public Licenseas published by the Free
  11. * Software Foundation; either version 2 of the License, or (at your option)
  12. * any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  16. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  17. * more details.
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program; if not, write to the Free Software Foundation, Inc.,
  20. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. #include <zebra.h>
  23. #include "memory.h"
  24. #include "thread.h"
  25. #include "linklist.h"
  26. #include "log.h"
  27. #include "stream.h"
  28. #include "vty.h"
  29. #include "hash.h"
  30. #include "prefix.h"
  31. #include "if.h"
  32. #include "checksum.h"
  33. #include "md5.h"
  34. #include "isisd/dict.h"
  35. #include "isisd/include-netbsd/iso.h"
  36. #include "isisd/isis_constants.h"
  37. #include "isisd/isis_common.h"
  38. #include "isisd/isis_flags.h"
  39. #include "isisd/isis_adjacency.h"
  40. #include "isisd/isis_circuit.h"
  41. #include "isisd/isis_network.h"
  42. #include "isisd/isis_misc.h"
  43. #include "isisd/isis_dr.h"
  44. #include "isisd/isis_tlv.h"
  45. #include "isisd/isisd.h"
  46. #include "isisd/isis_dynhn.h"
  47. #include "isisd/isis_lsp.h"
  48. #include "isisd/isis_pdu.h"
  49. #include "isisd/iso_checksum.h"
  50. #include "isisd/isis_csm.h"
  51. #include "isisd/isis_events.h"
  52. #define ISIS_MINIMUM_FIXED_HDR_LEN 15
  53. #define ISIS_MIN_PDU_LEN 13 /* partial seqnum pdu with id_len=2 */
  54. #ifndef PNBBY
  55. #define PNBBY 8
  56. #endif /* PNBBY */
  57. /* Utility mask array. */
  58. static const u_char maskbit[] = {
  59. 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff
  60. };
  61. /*
  62. * HELPER FUNCS
  63. */
  64. /*
  65. * Compares two sets of area addresses
  66. */
  67. static int
  68. area_match (struct list *left, struct list *right)
  69. {
  70. struct area_addr *addr1, *addr2;
  71. struct listnode *node1, *node2;
  72. for (ALL_LIST_ELEMENTS_RO (left, node1, addr1))
  73. {
  74. for (ALL_LIST_ELEMENTS_RO (right, node2, addr2))
  75. {
  76. if (addr1->addr_len == addr2->addr_len &&
  77. !memcmp (addr1->area_addr, addr2->area_addr, (int) addr1->addr_len))
  78. return 1; /* match */
  79. }
  80. }
  81. return 0; /* mismatch */
  82. }
  83. /*
  84. * Check if ip2 is in the ip1's network (function like Prefix.h:prefix_match() )
  85. * param ip1 the IS interface ip address structure
  86. * param ip2 the IIH's ip address
  87. * return 0 the IIH's IP is not in the IS's subnetwork
  88. * 1 the IIH's IP is in the IS's subnetwork
  89. */
  90. static int
  91. ip_same_subnet (struct prefix_ipv4 *ip1, struct in_addr *ip2)
  92. {
  93. u_char *addr1, *addr2;
  94. int shift, offset, offsetloop;
  95. int len;
  96. addr1 = (u_char *) & ip1->prefix.s_addr;
  97. addr2 = (u_char *) & ip2->s_addr;
  98. len = ip1->prefixlen;
  99. shift = len % PNBBY;
  100. offsetloop = offset = len / PNBBY;
  101. while (offsetloop--)
  102. if (addr1[offsetloop] != addr2[offsetloop])
  103. return 0;
  104. if (shift)
  105. if (maskbit[shift] & (addr1[offset] ^ addr2[offset]))
  106. return 0;
  107. return 1; /* match */
  108. }
  109. /*
  110. * Compares two set of ip addresses
  111. * param left the local interface's ip addresses
  112. * param right the iih interface's ip address
  113. * return 0 no match;
  114. * 1 match;
  115. */
  116. static int
  117. ip_match (struct list *left, struct list *right)
  118. {
  119. struct prefix_ipv4 *ip1;
  120. struct in_addr *ip2;
  121. struct listnode *node1, *node2;
  122. if ((left == NULL) || (right == NULL))
  123. return 0;
  124. for (ALL_LIST_ELEMENTS_RO (left, node1, ip1))
  125. {
  126. for (ALL_LIST_ELEMENTS_RO (right, node2, ip2))
  127. {
  128. if (ip_same_subnet (ip1, ip2))
  129. {
  130. return 1; /* match */
  131. }
  132. }
  133. }
  134. return 0;
  135. }
  136. /*
  137. * Checks whether we should accept a PDU of given level
  138. */
  139. static int
  140. accept_level (int level, int circuit_t)
  141. {
  142. int retval = ((circuit_t & level) == level); /* simple approach */
  143. return retval;
  144. }
  145. /*
  146. * Verify authentication information
  147. * Support cleartext and HMAC MD5 authentication
  148. */
  149. static int
  150. authentication_check (struct isis_passwd *remote, struct isis_passwd *local,
  151. struct stream *stream, uint32_t auth_tlv_offset)
  152. {
  153. unsigned char digest[ISIS_AUTH_MD5_SIZE];
  154. /* Auth fail () - passwd type mismatch */
  155. if (local->type != remote->type)
  156. return ISIS_ERROR;
  157. switch (local->type)
  158. {
  159. /* No authentication required */
  160. case ISIS_PASSWD_TYPE_UNUSED:
  161. break;
  162. /* Cleartext (ISO 10589) */
  163. case ISIS_PASSWD_TYPE_CLEARTXT:
  164. /* Auth fail () - passwd len mismatch */
  165. if (remote->len != local->len)
  166. return ISIS_ERROR;
  167. return memcmp (local->passwd, remote->passwd, local->len);
  168. /* HMAC MD5 (RFC 3567) */
  169. case ISIS_PASSWD_TYPE_HMAC_MD5:
  170. /* Auth fail () - passwd len mismatch */
  171. if (remote->len != ISIS_AUTH_MD5_SIZE)
  172. return ISIS_ERROR;
  173. /* Set the authentication value to 0 before the check */
  174. memset (STREAM_DATA (stream) + auth_tlv_offset + 3, 0,
  175. ISIS_AUTH_MD5_SIZE);
  176. /* Compute the digest */
  177. hmac_md5 (STREAM_DATA (stream), stream_get_endp (stream),
  178. (unsigned char *) &(local->passwd), local->len,
  179. (unsigned char *) &digest);
  180. /* Copy back the authentication value after the check */
  181. memcpy (STREAM_DATA (stream) + auth_tlv_offset + 3,
  182. remote->passwd, ISIS_AUTH_MD5_SIZE);
  183. return memcmp (digest, remote->passwd, ISIS_AUTH_MD5_SIZE);
  184. default:
  185. zlog_err ("Unsupported authentication type");
  186. return ISIS_ERROR;
  187. }
  188. /* Authentication pass when no authentication is configured */
  189. return ISIS_OK;
  190. }
  191. static int
  192. lsp_authentication_check (struct stream *stream, struct isis_area *area,
  193. int level, struct isis_passwd *passwd)
  194. {
  195. struct isis_link_state_hdr *hdr;
  196. uint32_t expected = 0, found = 0, auth_tlv_offset = 0;
  197. uint16_t checksum, rem_lifetime, pdu_len;
  198. struct tlvs tlvs;
  199. int retval = ISIS_OK;
  200. hdr = (struct isis_link_state_hdr *) (STREAM_PNT (stream));
  201. pdu_len = ntohs (hdr->pdu_len);
  202. expected |= TLVFLAG_AUTH_INFO;
  203. auth_tlv_offset = stream_get_getp (stream) + ISIS_LSP_HDR_LEN;
  204. retval = parse_tlvs (area->area_tag, STREAM_PNT (stream) + ISIS_LSP_HDR_LEN,
  205. pdu_len - ISIS_FIXED_HDR_LEN - ISIS_LSP_HDR_LEN,
  206. &expected, &found, &tlvs, &auth_tlv_offset);
  207. if (retval != ISIS_OK)
  208. {
  209. zlog_err ("ISIS-Upd (%s): Parse failed L%d LSP %s, seq 0x%08x, "
  210. "cksum 0x%04x, lifetime %us, len %u",
  211. area->area_tag, level, rawlspid_print (hdr->lsp_id),
  212. ntohl (hdr->seq_num), ntohs (hdr->checksum),
  213. ntohs (hdr->rem_lifetime), pdu_len);
  214. if ((isis->debugs & DEBUG_UPDATE_PACKETS) &&
  215. (isis->debugs & DEBUG_PACKET_DUMP))
  216. zlog_dump_data (STREAM_DATA (stream), stream_get_endp (stream));
  217. return retval;
  218. }
  219. if (!(found & TLVFLAG_AUTH_INFO))
  220. {
  221. zlog_err ("No authentication tlv in LSP");
  222. return ISIS_ERROR;
  223. }
  224. if (tlvs.auth_info.type != ISIS_PASSWD_TYPE_CLEARTXT &&
  225. tlvs.auth_info.type != ISIS_PASSWD_TYPE_HMAC_MD5)
  226. {
  227. zlog_err ("Unknown authentication type in LSP");
  228. return ISIS_ERROR;
  229. }
  230. /*
  231. * RFC 5304 set checksum and remaining lifetime to zero before
  232. * verification and reset to old values after verification.
  233. */
  234. checksum = hdr->checksum;
  235. rem_lifetime = hdr->rem_lifetime;
  236. hdr->checksum = 0;
  237. hdr->rem_lifetime = 0;
  238. retval = authentication_check (&tlvs.auth_info, passwd, stream,
  239. auth_tlv_offset);
  240. hdr->checksum = checksum;
  241. hdr->rem_lifetime = rem_lifetime;
  242. return retval;
  243. }
  244. /*
  245. * Processing helper functions
  246. */
  247. static void
  248. del_addr (void *val)
  249. {
  250. XFREE (MTYPE_ISIS_TMP, val);
  251. }
  252. static void
  253. tlvs_to_adj_area_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
  254. {
  255. struct listnode *node;
  256. struct area_addr *area_addr, *malloced;
  257. if (adj->area_addrs)
  258. {
  259. adj->area_addrs->del = del_addr;
  260. list_delete (adj->area_addrs);
  261. }
  262. adj->area_addrs = list_new ();
  263. if (tlvs->area_addrs)
  264. {
  265. for (ALL_LIST_ELEMENTS_RO (tlvs->area_addrs, node, area_addr))
  266. {
  267. malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct area_addr));
  268. memcpy (malloced, area_addr, sizeof (struct area_addr));
  269. listnode_add (adj->area_addrs, malloced);
  270. }
  271. }
  272. }
  273. static int
  274. tlvs_to_adj_nlpids (struct tlvs *tlvs, struct isis_adjacency *adj)
  275. {
  276. int i;
  277. struct nlpids *tlv_nlpids;
  278. if (tlvs->nlpids)
  279. {
  280. tlv_nlpids = tlvs->nlpids;
  281. if (tlv_nlpids->count > array_size (adj->nlpids.nlpids))
  282. return 1;
  283. adj->nlpids.count = tlv_nlpids->count;
  284. for (i = 0; i < tlv_nlpids->count; i++)
  285. {
  286. adj->nlpids.nlpids[i] = tlv_nlpids->nlpids[i];
  287. }
  288. }
  289. return 0;
  290. }
  291. static void
  292. tlvs_to_adj_ipv4_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
  293. {
  294. struct listnode *node;
  295. struct in_addr *ipv4_addr, *malloced;
  296. if (adj->ipv4_addrs)
  297. {
  298. adj->ipv4_addrs->del = del_addr;
  299. list_delete (adj->ipv4_addrs);
  300. }
  301. adj->ipv4_addrs = list_new ();
  302. if (tlvs->ipv4_addrs)
  303. {
  304. for (ALL_LIST_ELEMENTS_RO (tlvs->ipv4_addrs, node, ipv4_addr))
  305. {
  306. malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in_addr));
  307. memcpy (malloced, ipv4_addr, sizeof (struct in_addr));
  308. listnode_add (adj->ipv4_addrs, malloced);
  309. }
  310. }
  311. }
  312. #ifdef HAVE_IPV6
  313. static void
  314. tlvs_to_adj_ipv6_addrs (struct tlvs *tlvs, struct isis_adjacency *adj)
  315. {
  316. struct listnode *node;
  317. struct in6_addr *ipv6_addr, *malloced;
  318. if (adj->ipv6_addrs)
  319. {
  320. adj->ipv6_addrs->del = del_addr;
  321. list_delete (adj->ipv6_addrs);
  322. }
  323. adj->ipv6_addrs = list_new ();
  324. if (tlvs->ipv6_addrs)
  325. {
  326. for (ALL_LIST_ELEMENTS_RO (tlvs->ipv6_addrs, node, ipv6_addr))
  327. {
  328. malloced = XMALLOC (MTYPE_ISIS_TMP, sizeof (struct in6_addr));
  329. memcpy (malloced, ipv6_addr, sizeof (struct in6_addr));
  330. listnode_add (adj->ipv6_addrs, malloced);
  331. }
  332. }
  333. }
  334. #endif /* HAVE_IPV6 */
  335. /*
  336. * RECEIVE SIDE
  337. */
  338. /*
  339. * Process P2P IIH
  340. * ISO - 10589
  341. * Section 8.2.5 - Receiving point-to-point IIH PDUs
  342. *
  343. */
  344. static int
  345. process_p2p_hello (struct isis_circuit *circuit)
  346. {
  347. int retval = ISIS_OK;
  348. struct isis_p2p_hello_hdr *hdr;
  349. struct isis_adjacency *adj;
  350. u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;
  351. uint16_t pdu_len;
  352. struct tlvs tlvs;
  353. int v4_usable = 0, v6_usable = 0;
  354. if (isis->debugs & DEBUG_ADJ_PACKETS)
  355. {
  356. zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH on %s, cirType %s, cirID %u",
  357. circuit->area->area_tag, circuit->interface->name,
  358. circuit_t2string (circuit->is_type), circuit->circuit_id);
  359. if (isis->debugs & DEBUG_PACKET_DUMP)
  360. zlog_dump_data (STREAM_DATA (circuit->rcv_stream),
  361. stream_get_endp (circuit->rcv_stream));
  362. }
  363. if (circuit->circ_type != CIRCUIT_T_P2P)
  364. {
  365. zlog_warn ("p2p hello on non p2p circuit");
  366. return ISIS_WARNING;
  367. }
  368. if ((stream_get_endp (circuit->rcv_stream) -
  369. stream_get_getp (circuit->rcv_stream)) < ISIS_P2PHELLO_HDRLEN)
  370. {
  371. zlog_warn ("Packet too short");
  372. return ISIS_WARNING;
  373. }
  374. /* 8.2.5.1 PDU acceptance tests */
  375. /* 8.2.5.1 a) external domain untrue */
  376. /* FIXME: not useful at all? */
  377. /* 8.2.5.1 b) ID Length mismatch */
  378. /* checked at the handle_pdu */
  379. /* 8.2.5.2 IIH PDU Processing */
  380. /* 8.2.5.2 a) 1) Maximum Area Addresses */
  381. /* Already checked, and can also be ommited */
  382. /*
  383. * Get the header
  384. */
  385. hdr = (struct isis_p2p_hello_hdr *) STREAM_PNT (circuit->rcv_stream);
  386. pdu_len = ntohs (hdr->pdu_len);
  387. if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_P2PHELLO_HDRLEN) ||
  388. pdu_len > ISO_MTU(circuit) ||
  389. pdu_len > stream_get_endp (circuit->rcv_stream))
  390. {
  391. zlog_warn ("ISIS-Adj (%s): Rcvd P2P IIH from (%s) with "
  392. "invalid pdu length %d",
  393. circuit->area->area_tag, circuit->interface->name, pdu_len);
  394. return ISIS_WARNING;
  395. }
  396. /*
  397. * Set the stream endp to PDU length, ignoring additional padding
  398. * introduced by transport chips.
  399. */
  400. if (pdu_len < stream_get_endp (circuit->rcv_stream))
  401. stream_set_endp (circuit->rcv_stream, pdu_len);
  402. stream_forward_getp (circuit->rcv_stream, ISIS_P2PHELLO_HDRLEN);
  403. /*
  404. * Lets get the TLVS now
  405. */
  406. expected |= TLVFLAG_AREA_ADDRS;
  407. expected |= TLVFLAG_AUTH_INFO;
  408. expected |= TLVFLAG_NLPID;
  409. expected |= TLVFLAG_IPV4_ADDR;
  410. expected |= TLVFLAG_IPV6_ADDR;
  411. auth_tlv_offset = stream_get_getp (circuit->rcv_stream);
  412. retval = parse_tlvs (circuit->area->area_tag,
  413. STREAM_PNT (circuit->rcv_stream),
  414. pdu_len - ISIS_P2PHELLO_HDRLEN - ISIS_FIXED_HDR_LEN,
  415. &expected, &found, &tlvs, &auth_tlv_offset);
  416. if (retval > ISIS_WARNING)
  417. {
  418. zlog_warn ("parse_tlvs() failed");
  419. free_tlvs (&tlvs);
  420. return retval;
  421. };
  422. if (!(found & TLVFLAG_AREA_ADDRS))
  423. {
  424. zlog_warn ("No Area addresses TLV in P2P IS to IS hello");
  425. free_tlvs (&tlvs);
  426. return ISIS_WARNING;
  427. }
  428. if (!(found & TLVFLAG_NLPID))
  429. {
  430. zlog_warn ("No supported protocols TLV in P2P IS to IS hello");
  431. free_tlvs (&tlvs);
  432. return ISIS_WARNING;
  433. }
  434. /* 8.2.5.1 c) Authentication */
  435. if (circuit->passwd.type)
  436. {
  437. if (!(found & TLVFLAG_AUTH_INFO) ||
  438. authentication_check (&tlvs.auth_info, &circuit->passwd,
  439. circuit->rcv_stream, auth_tlv_offset))
  440. {
  441. isis_event_auth_failure (circuit->area->area_tag,
  442. "P2P hello authentication failure",
  443. hdr->source_id);
  444. free_tlvs (&tlvs);
  445. return ISIS_OK;
  446. }
  447. }
  448. /*
  449. * check if it's own interface ip match iih ip addrs
  450. */
  451. if (found & TLVFLAG_IPV4_ADDR)
  452. {
  453. if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
  454. v4_usable = 1;
  455. else
  456. zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap "
  457. "in P2P IIH from %s\n", circuit->interface->name);
  458. }
  459. #ifndef HAVE_IPV6
  460. else /* !(found & TLVFLAG_IPV4_ADDR) */
  461. zlog_warn ("ISIS-Adj: no IPv4 in P2P IIH from %s "
  462. "(this isisd has no IPv6)\n", circuit->interface->name);
  463. #else
  464. if (found & TLVFLAG_IPV6_ADDR)
  465. {
  466. /* TBA: check that we have a linklocal ourselves? */
  467. struct listnode *node;
  468. struct in6_addr *ip;
  469. for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip))
  470. if (IN6_IS_ADDR_LINKLOCAL (ip))
  471. {
  472. v6_usable = 1;
  473. break;
  474. }
  475. if (!v6_usable)
  476. zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local "
  477. "in P2P IIH from %s\n", circuit->interface->name);
  478. }
  479. if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
  480. zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in P2P IIH from %s\n",
  481. circuit->interface->name);
  482. #endif
  483. if (!v6_usable && !v4_usable)
  484. {
  485. free_tlvs (&tlvs);
  486. return ISIS_WARNING;
  487. }
  488. /*
  489. * it's own p2p IIH PDU - discard
  490. */
  491. if (!memcmp (hdr->source_id, isis->sysid, ISIS_SYS_ID_LEN))
  492. {
  493. zlog_warn ("ISIS-Adj (%s): it's own IIH PDU - discarded",
  494. circuit->area->area_tag);
  495. free_tlvs (&tlvs);
  496. return ISIS_WARNING;
  497. }
  498. /*
  499. * My interpertation of the ISO, if no adj exists we will create one for
  500. * the circuit
  501. */
  502. adj = circuit->u.p2p.neighbor;
  503. /* If an adjacency exists, check it is with the source of the hello
  504. * packets */
  505. if (adj)
  506. {
  507. if (memcmp(hdr->source_id, adj->sysid, ISIS_SYS_ID_LEN))
  508. {
  509. zlog_debug("hello source and adjacency do not match, set adj down\n");
  510. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "adj do not exist");
  511. return 0;
  512. }
  513. }
  514. if (!adj || adj->level != hdr->circuit_t)
  515. {
  516. if (!adj)
  517. {
  518. adj = isis_new_adj (hdr->source_id, NULL, hdr->circuit_t, circuit);
  519. if (adj == NULL)
  520. return ISIS_ERROR;
  521. }
  522. else
  523. {
  524. adj->level = hdr->circuit_t;
  525. }
  526. circuit->u.p2p.neighbor = adj;
  527. /* Build lsp with the new neighbor entry when a new
  528. * adjacency is formed. Set adjacency circuit type to
  529. * IIH PDU header circuit type before lsp is regenerated
  530. * when an adjacency is up. This will result in the new
  531. * adjacency entry getting added to the lsp tlv neighbor list.
  532. */
  533. adj->circuit_t = hdr->circuit_t;
  534. isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
  535. adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
  536. }
  537. /* 8.2.6 Monitoring point-to-point adjacencies */
  538. adj->hold_time = ntohs (hdr->hold_time);
  539. adj->last_upd = time (NULL);
  540. /* we do this now because the adj may not survive till the end... */
  541. tlvs_to_adj_area_addrs (&tlvs, adj);
  542. /* which protocol are spoken ??? */
  543. if (tlvs_to_adj_nlpids (&tlvs, adj))
  544. {
  545. free_tlvs (&tlvs);
  546. return ISIS_WARNING;
  547. }
  548. /* we need to copy addresses to the adj */
  549. if (found & TLVFLAG_IPV4_ADDR)
  550. tlvs_to_adj_ipv4_addrs (&tlvs, adj);
  551. #ifdef HAVE_IPV6
  552. if (found & TLVFLAG_IPV6_ADDR)
  553. tlvs_to_adj_ipv6_addrs (&tlvs, adj);
  554. #endif /* HAVE_IPV6 */
  555. /* lets take care of the expiry */
  556. THREAD_TIMER_OFF (adj->t_expire);
  557. THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
  558. (long) adj->hold_time);
  559. /* 8.2.5.2 a) a match was detected */
  560. if (area_match (circuit->area->area_addrs, tlvs.area_addrs))
  561. {
  562. /* 8.2.5.2 a) 2) If the system is L1 - table 5 */
  563. if (circuit->area->is_type == IS_LEVEL_1)
  564. {
  565. switch (hdr->circuit_t)
  566. {
  567. case IS_LEVEL_1:
  568. case IS_LEVEL_1_AND_2:
  569. if (adj->adj_state != ISIS_ADJ_UP)
  570. {
  571. /* (4) adj state up */
  572. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  573. /* (5) adj usage level 1 */
  574. adj->adj_usage = ISIS_ADJ_LEVEL1;
  575. }
  576. else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
  577. {
  578. ; /* accept */
  579. }
  580. break;
  581. case IS_LEVEL_2:
  582. if (adj->adj_state != ISIS_ADJ_UP)
  583. {
  584. /* (7) reject - wrong system type event */
  585. zlog_warn ("wrongSystemType");
  586. free_tlvs (&tlvs);
  587. return ISIS_WARNING; /* Reject */
  588. }
  589. else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
  590. {
  591. /* (6) down - wrong system */
  592. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  593. }
  594. break;
  595. }
  596. }
  597. /* 8.2.5.2 a) 3) If the system is L1L2 - table 6 */
  598. if (circuit->area->is_type == IS_LEVEL_1_AND_2)
  599. {
  600. switch (hdr->circuit_t)
  601. {
  602. case IS_LEVEL_1:
  603. if (adj->adj_state != ISIS_ADJ_UP)
  604. {
  605. /* (6) adj state up */
  606. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  607. /* (7) adj usage level 1 */
  608. adj->adj_usage = ISIS_ADJ_LEVEL1;
  609. }
  610. else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
  611. {
  612. ; /* accept */
  613. }
  614. else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
  615. (adj->adj_usage == ISIS_ADJ_LEVEL2))
  616. {
  617. /* (8) down - wrong system */
  618. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  619. }
  620. break;
  621. case IS_LEVEL_2:
  622. if (adj->adj_state != ISIS_ADJ_UP)
  623. {
  624. /* (6) adj state up */
  625. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  626. /* (9) adj usage level 2 */
  627. adj->adj_usage = ISIS_ADJ_LEVEL2;
  628. }
  629. else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
  630. (adj->adj_usage == ISIS_ADJ_LEVEL1AND2))
  631. {
  632. /* (8) down - wrong system */
  633. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  634. }
  635. else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
  636. {
  637. ; /* Accept */
  638. }
  639. break;
  640. case IS_LEVEL_1_AND_2:
  641. if (adj->adj_state != ISIS_ADJ_UP)
  642. {
  643. /* (6) adj state up */
  644. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  645. /* (10) adj usage level 1 */
  646. adj->adj_usage = ISIS_ADJ_LEVEL1AND2;
  647. }
  648. else if ((adj->adj_usage == ISIS_ADJ_LEVEL1) ||
  649. (adj->adj_usage == ISIS_ADJ_LEVEL2))
  650. {
  651. /* (8) down - wrong system */
  652. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  653. }
  654. else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
  655. {
  656. ; /* Accept */
  657. }
  658. break;
  659. }
  660. }
  661. /* 8.2.5.2 a) 4) If the system is L2 - table 7 */
  662. if (circuit->area->is_type == IS_LEVEL_2)
  663. {
  664. switch (hdr->circuit_t)
  665. {
  666. case IS_LEVEL_1:
  667. if (adj->adj_state != ISIS_ADJ_UP)
  668. {
  669. /* (5) reject - wrong system type event */
  670. zlog_warn ("wrongSystemType");
  671. free_tlvs (&tlvs);
  672. return ISIS_WARNING; /* Reject */
  673. }
  674. else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
  675. (adj->adj_usage == ISIS_ADJ_LEVEL2))
  676. {
  677. /* (6) down - wrong system */
  678. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  679. }
  680. break;
  681. case IS_LEVEL_1_AND_2:
  682. case IS_LEVEL_2:
  683. if (adj->adj_state != ISIS_ADJ_UP)
  684. {
  685. /* (7) adj state up */
  686. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  687. /* (8) adj usage level 2 */
  688. adj->adj_usage = ISIS_ADJ_LEVEL2;
  689. }
  690. else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
  691. {
  692. /* (6) down - wrong system */
  693. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  694. }
  695. else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
  696. {
  697. ; /* Accept */
  698. }
  699. break;
  700. }
  701. }
  702. }
  703. /* 8.2.5.2 b) if no match was detected */
  704. else if (listcount (circuit->area->area_addrs) > 0)
  705. {
  706. if (circuit->area->is_type == IS_LEVEL_1)
  707. {
  708. /* 8.2.5.2 b) 1) is_type L1 and adj is not up */
  709. if (adj->adj_state != ISIS_ADJ_UP)
  710. {
  711. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
  712. /* 8.2.5.2 b) 2)is_type L1 and adj is up */
  713. }
  714. else
  715. {
  716. isis_adj_state_change (adj, ISIS_ADJ_DOWN,
  717. "Down - Area Mismatch");
  718. }
  719. }
  720. /* 8.2.5.2 b 3 If the system is L2 or L1L2 - table 8 */
  721. else
  722. {
  723. switch (hdr->circuit_t)
  724. {
  725. case IS_LEVEL_1:
  726. if (adj->adj_state != ISIS_ADJ_UP)
  727. {
  728. /* (6) reject - Area Mismatch event */
  729. zlog_warn ("AreaMismatch");
  730. free_tlvs (&tlvs);
  731. return ISIS_WARNING; /* Reject */
  732. }
  733. else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
  734. {
  735. /* (7) down - area mismatch */
  736. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
  737. }
  738. else if ((adj->adj_usage == ISIS_ADJ_LEVEL1AND2) ||
  739. (adj->adj_usage == ISIS_ADJ_LEVEL2))
  740. {
  741. /* (7) down - wrong system */
  742. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  743. }
  744. break;
  745. case IS_LEVEL_1_AND_2:
  746. case IS_LEVEL_2:
  747. if (adj->adj_state != ISIS_ADJ_UP)
  748. {
  749. /* (8) adj state up */
  750. isis_adj_state_change (adj, ISIS_ADJ_UP, NULL);
  751. /* (9) adj usage level 2 */
  752. adj->adj_usage = ISIS_ADJ_LEVEL2;
  753. }
  754. else if (adj->adj_usage == ISIS_ADJ_LEVEL1)
  755. {
  756. /* (7) down - wrong system */
  757. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Wrong System");
  758. }
  759. else if (adj->adj_usage == ISIS_ADJ_LEVEL1AND2)
  760. {
  761. if (hdr->circuit_t == IS_LEVEL_2)
  762. {
  763. /* (7) down - wrong system */
  764. isis_adj_state_change (adj, ISIS_ADJ_DOWN,
  765. "Wrong System");
  766. }
  767. else
  768. {
  769. /* (7) down - area mismatch */
  770. isis_adj_state_change (adj, ISIS_ADJ_DOWN,
  771. "Area Mismatch");
  772. }
  773. }
  774. else if (adj->adj_usage == ISIS_ADJ_LEVEL2)
  775. {
  776. ; /* Accept */
  777. }
  778. break;
  779. }
  780. }
  781. }
  782. else
  783. {
  784. /* down - area mismatch */
  785. isis_adj_state_change (adj, ISIS_ADJ_DOWN, "Area Mismatch");
  786. }
  787. /* 8.2.5.2 c) if the action was up - comparing circuit IDs */
  788. /* FIXME - Missing parts */
  789. /* some of my own understanding of the ISO, why the heck does
  790. * it not say what should I change the system_type to...
  791. */
  792. switch (adj->adj_usage)
  793. {
  794. case ISIS_ADJ_LEVEL1:
  795. adj->sys_type = ISIS_SYSTYPE_L1_IS;
  796. break;
  797. case ISIS_ADJ_LEVEL2:
  798. adj->sys_type = ISIS_SYSTYPE_L2_IS;
  799. break;
  800. case ISIS_ADJ_LEVEL1AND2:
  801. adj->sys_type = ISIS_SYSTYPE_L2_IS;
  802. break;
  803. case ISIS_ADJ_NONE:
  804. adj->sys_type = ISIS_SYSTYPE_UNKNOWN;
  805. break;
  806. }
  807. if (isis->debugs & DEBUG_ADJ_PACKETS)
  808. {
  809. zlog_debug ("ISIS-Adj (%s): Rcvd P2P IIH from (%s), cir type %s,"
  810. " cir id %02d, length %d",
  811. circuit->area->area_tag, circuit->interface->name,
  812. circuit_t2string (circuit->is_type),
  813. circuit->circuit_id, pdu_len);
  814. }
  815. free_tlvs (&tlvs);
  816. return retval;
  817. }
  818. /*
  819. * Process IS-IS LAN Level 1/2 Hello PDU
  820. */
  821. static int
  822. process_lan_hello (int level, struct isis_circuit *circuit, const u_char *ssnpa)
  823. {
  824. int retval = ISIS_OK;
  825. struct isis_lan_hello_hdr hdr;
  826. struct isis_adjacency *adj;
  827. u_int32_t expected = 0, found = 0, auth_tlv_offset = 0;
  828. struct tlvs tlvs;
  829. u_char *snpa;
  830. struct listnode *node;
  831. int v4_usable = 0, v6_usable = 0;
  832. if (isis->debugs & DEBUG_ADJ_PACKETS)
  833. {
  834. zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH on %s, cirType %s, "
  835. "cirID %u",
  836. circuit->area->area_tag, level, circuit->interface->name,
  837. circuit_t2string (circuit->is_type), circuit->circuit_id);
  838. if (isis->debugs & DEBUG_PACKET_DUMP)
  839. zlog_dump_data (STREAM_DATA (circuit->rcv_stream),
  840. stream_get_endp (circuit->rcv_stream));
  841. }
  842. if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  843. {
  844. zlog_warn ("lan hello on non broadcast circuit");
  845. return ISIS_WARNING;
  846. }
  847. if ((stream_get_endp (circuit->rcv_stream) -
  848. stream_get_getp (circuit->rcv_stream)) < ISIS_LANHELLO_HDRLEN)
  849. {
  850. zlog_warn ("Packet too short");
  851. return ISIS_WARNING;
  852. }
  853. if (circuit->ext_domain)
  854. {
  855. zlog_debug ("level %d LAN Hello received over circuit with "
  856. "externalDomain = true", level);
  857. return ISIS_WARNING;
  858. }
  859. if (!accept_level (level, circuit->is_type))
  860. {
  861. if (isis->debugs & DEBUG_ADJ_PACKETS)
  862. {
  863. zlog_debug ("ISIS-Adj (%s): Interface level mismatch, %s",
  864. circuit->area->area_tag, circuit->interface->name);
  865. }
  866. return ISIS_WARNING;
  867. }
  868. #if 0
  869. /* Cisco's debug message compatability */
  870. if (!accept_level (level, circuit->area->is_type))
  871. {
  872. if (isis->debugs & DEBUG_ADJ_PACKETS)
  873. {
  874. zlog_debug ("ISIS-Adj (%s): is type mismatch",
  875. circuit->area->area_tag);
  876. }
  877. return ISIS_WARNING;
  878. }
  879. #endif
  880. /*
  881. * Fill the header
  882. */
  883. hdr.circuit_t = stream_getc (circuit->rcv_stream);
  884. stream_get (hdr.source_id, circuit->rcv_stream, ISIS_SYS_ID_LEN);
  885. hdr.hold_time = stream_getw (circuit->rcv_stream);
  886. hdr.pdu_len = stream_getw (circuit->rcv_stream);
  887. hdr.prio = stream_getc (circuit->rcv_stream);
  888. stream_get (hdr.lan_id, circuit->rcv_stream, ISIS_SYS_ID_LEN + 1);
  889. if (hdr.pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LANHELLO_HDRLEN) ||
  890. hdr.pdu_len > ISO_MTU(circuit) ||
  891. hdr.pdu_len > stream_get_endp (circuit->rcv_stream))
  892. {
  893. zlog_warn ("ISIS-Adj (%s): Rcvd LAN IIH from (%s) with "
  894. "invalid pdu length %d",
  895. circuit->area->area_tag, circuit->interface->name,
  896. hdr.pdu_len);
  897. return ISIS_WARNING;
  898. }
  899. /*
  900. * Set the stream endp to PDU length, ignoring additional padding
  901. * introduced by transport chips.
  902. */
  903. if (hdr.pdu_len < stream_get_endp (circuit->rcv_stream))
  904. stream_set_endp (circuit->rcv_stream, hdr.pdu_len);
  905. if (hdr.circuit_t != IS_LEVEL_1 &&
  906. hdr.circuit_t != IS_LEVEL_2 &&
  907. hdr.circuit_t != IS_LEVEL_1_AND_2 &&
  908. (level & hdr.circuit_t) == 0)
  909. {
  910. zlog_err ("Level %d LAN Hello with Circuit Type %d", level,
  911. hdr.circuit_t);
  912. return ISIS_ERROR;
  913. }
  914. /*
  915. * Then get the tlvs
  916. */
  917. expected |= TLVFLAG_AUTH_INFO;
  918. expected |= TLVFLAG_AREA_ADDRS;
  919. expected |= TLVFLAG_LAN_NEIGHS;
  920. expected |= TLVFLAG_NLPID;
  921. expected |= TLVFLAG_IPV4_ADDR;
  922. expected |= TLVFLAG_IPV6_ADDR;
  923. auth_tlv_offset = stream_get_getp (circuit->rcv_stream);
  924. retval = parse_tlvs (circuit->area->area_tag,
  925. STREAM_PNT (circuit->rcv_stream),
  926. hdr.pdu_len - ISIS_LANHELLO_HDRLEN - ISIS_FIXED_HDR_LEN,
  927. &expected, &found, &tlvs,
  928. &auth_tlv_offset);
  929. if (retval > ISIS_WARNING)
  930. {
  931. zlog_warn ("parse_tlvs() failed");
  932. goto out;
  933. }
  934. if (!(found & TLVFLAG_AREA_ADDRS))
  935. {
  936. zlog_warn ("No Area addresses TLV in Level %d LAN IS to IS hello",
  937. level);
  938. retval = ISIS_WARNING;
  939. goto out;
  940. }
  941. if (!(found & TLVFLAG_NLPID))
  942. {
  943. zlog_warn ("No supported protocols TLV in Level %d LAN IS to IS hello",
  944. level);
  945. retval = ISIS_WARNING;
  946. goto out;
  947. }
  948. /* Verify authentication, either cleartext of HMAC MD5 */
  949. if (circuit->passwd.type)
  950. {
  951. if (!(found & TLVFLAG_AUTH_INFO) ||
  952. authentication_check (&tlvs.auth_info, &circuit->passwd,
  953. circuit->rcv_stream, auth_tlv_offset))
  954. {
  955. isis_event_auth_failure (circuit->area->area_tag,
  956. "LAN hello authentication failure",
  957. hdr.source_id);
  958. retval = ISIS_WARNING;
  959. goto out;
  960. }
  961. }
  962. if (!memcmp (hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN))
  963. {
  964. zlog_warn ("ISIS-Adj (%s): duplicate system ID on interface %s",
  965. circuit->area->area_tag, circuit->interface->name);
  966. return ISIS_WARNING;
  967. }
  968. /*
  969. * Accept the level 1 adjacency only if a match between local and
  970. * remote area addresses is found
  971. */
  972. if (listcount (circuit->area->area_addrs) == 0 ||
  973. (level == IS_LEVEL_1 &&
  974. area_match (circuit->area->area_addrs, tlvs.area_addrs) == 0))
  975. {
  976. if (isis->debugs & DEBUG_ADJ_PACKETS)
  977. {
  978. zlog_debug ("ISIS-Adj (%s): Area mismatch, level %d IIH on %s",
  979. circuit->area->area_tag, level,
  980. circuit->interface->name);
  981. }
  982. retval = ISIS_OK;
  983. goto out;
  984. }
  985. /*
  986. * it's own IIH PDU - discard silently
  987. */
  988. if (!memcmp (circuit->u.bc.snpa, ssnpa, ETH_ALEN))
  989. {
  990. zlog_debug ("ISIS-Adj (%s): it's own IIH PDU - discarded",
  991. circuit->area->area_tag);
  992. retval = ISIS_OK;
  993. goto out;
  994. }
  995. /*
  996. * check if it's own interface ip match iih ip addrs
  997. */
  998. if (found & TLVFLAG_IPV4_ADDR)
  999. {
  1000. if (ip_match (circuit->ip_addrs, tlvs.ipv4_addrs))
  1001. v4_usable = 1;
  1002. else
  1003. zlog_warn ("ISIS-Adj: IPv4 addresses present but no overlap "
  1004. "in LAN IIH from %s\n", circuit->interface->name);
  1005. }
  1006. #ifndef HAVE_IPV6
  1007. else /* !(found & TLVFLAG_IPV4_ADDR) */
  1008. zlog_warn ("ISIS-Adj: no IPv4 in LAN IIH from %s "
  1009. "(this isisd has no IPv6)\n", circuit->interface->name);
  1010. #else
  1011. if (found & TLVFLAG_IPV6_ADDR)
  1012. {
  1013. /* TBA: check that we have a linklocal ourselves? */
  1014. struct listnode *node;
  1015. struct in6_addr *ip;
  1016. for (ALL_LIST_ELEMENTS_RO (tlvs.ipv6_addrs, node, ip))
  1017. if (IN6_IS_ADDR_LINKLOCAL (ip))
  1018. {
  1019. v6_usable = 1;
  1020. break;
  1021. }
  1022. if (!v6_usable)
  1023. zlog_warn ("ISIS-Adj: IPv6 addresses present but no link-local "
  1024. "in LAN IIH from %s\n", circuit->interface->name);
  1025. }
  1026. if (!(found & (TLVFLAG_IPV4_ADDR | TLVFLAG_IPV6_ADDR)))
  1027. zlog_warn ("ISIS-Adj: neither IPv4 nor IPv6 addr in LAN IIH from %s\n",
  1028. circuit->interface->name);
  1029. #endif
  1030. if (!v6_usable && !v4_usable)
  1031. {
  1032. free_tlvs (&tlvs);
  1033. return ISIS_WARNING;
  1034. }
  1035. adj = isis_adj_lookup (hdr.source_id, circuit->u.bc.adjdb[level - 1]);
  1036. if ((adj == NULL) || (memcmp(adj->snpa, ssnpa, ETH_ALEN)) ||
  1037. (adj->level != level))
  1038. {
  1039. if (!adj)
  1040. {
  1041. /*
  1042. * Do as in 8.4.2.5
  1043. */
  1044. adj = isis_new_adj (hdr.source_id, ssnpa, level, circuit);
  1045. if (adj == NULL)
  1046. {
  1047. retval = ISIS_ERROR;
  1048. goto out;
  1049. }
  1050. }
  1051. else
  1052. {
  1053. if (ssnpa) {
  1054. memcpy (adj->snpa, ssnpa, 6);
  1055. } else {
  1056. memset (adj->snpa, ' ', 6);
  1057. }
  1058. adj->level = level;
  1059. }
  1060. isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING, NULL);
  1061. if (level == IS_LEVEL_1)
  1062. adj->sys_type = ISIS_SYSTYPE_L1_IS;
  1063. else
  1064. adj->sys_type = ISIS_SYSTYPE_L2_IS;
  1065. list_delete_all_node (circuit->u.bc.lan_neighs[level - 1]);
  1066. isis_adj_build_neigh_list (circuit->u.bc.adjdb[level - 1],
  1067. circuit->u.bc.lan_neighs[level - 1]);
  1068. }
  1069. if(adj->dis_record[level-1].dis==ISIS_IS_DIS)
  1070. switch (level)
  1071. {
  1072. case 1:
  1073. if (memcmp (circuit->u.bc.l1_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
  1074. {
  1075. thread_add_event (master, isis_event_dis_status_change, circuit, 0);
  1076. memcpy (&circuit->u.bc.l1_desig_is, hdr.lan_id,
  1077. ISIS_SYS_ID_LEN + 1);
  1078. }
  1079. break;
  1080. case 2:
  1081. if (memcmp (circuit->u.bc.l2_desig_is, hdr.lan_id, ISIS_SYS_ID_LEN + 1))
  1082. {
  1083. thread_add_event (master, isis_event_dis_status_change, circuit, 0);
  1084. memcpy (&circuit->u.bc.l2_desig_is, hdr.lan_id,
  1085. ISIS_SYS_ID_LEN + 1);
  1086. }
  1087. break;
  1088. }
  1089. adj->hold_time = hdr.hold_time;
  1090. adj->last_upd = time (NULL);
  1091. adj->prio[level - 1] = hdr.prio;
  1092. memcpy (adj->lanid, hdr.lan_id, ISIS_SYS_ID_LEN + 1);
  1093. tlvs_to_adj_area_addrs (&tlvs, adj);
  1094. /* which protocol are spoken ??? */
  1095. if (tlvs_to_adj_nlpids (&tlvs, adj))
  1096. {
  1097. retval = ISIS_WARNING;
  1098. goto out;
  1099. }
  1100. /* we need to copy addresses to the adj */
  1101. if (found & TLVFLAG_IPV4_ADDR)
  1102. tlvs_to_adj_ipv4_addrs (&tlvs, adj);
  1103. #ifdef HAVE_IPV6
  1104. if (found & TLVFLAG_IPV6_ADDR)
  1105. tlvs_to_adj_ipv6_addrs (&tlvs, adj);
  1106. #endif /* HAVE_IPV6 */
  1107. adj->circuit_t = hdr.circuit_t;
  1108. /* lets take care of the expiry */
  1109. THREAD_TIMER_OFF (adj->t_expire);
  1110. THREAD_TIMER_ON (master, adj->t_expire, isis_adj_expire, adj,
  1111. (long) adj->hold_time);
  1112. /*
  1113. * If the snpa for this circuit is found from LAN Neighbours TLV
  1114. * we have two-way communication -> adjacency can be put to state "up"
  1115. */
  1116. if (found & TLVFLAG_LAN_NEIGHS)
  1117. {
  1118. if (adj->adj_state != ISIS_ADJ_UP)
  1119. {
  1120. for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa))
  1121. {
  1122. if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN))
  1123. {
  1124. isis_adj_state_change (adj, ISIS_ADJ_UP,
  1125. "own SNPA found in LAN Neighbours TLV");
  1126. }
  1127. }
  1128. }
  1129. else
  1130. {
  1131. int found = 0;
  1132. for (ALL_LIST_ELEMENTS_RO (tlvs.lan_neighs, node, snpa))
  1133. if (!memcmp (snpa, circuit->u.bc.snpa, ETH_ALEN))
  1134. {
  1135. found = 1;
  1136. break;
  1137. }
  1138. if (found == 0)
  1139. isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING,
  1140. "own SNPA not found in LAN Neighbours TLV");
  1141. }
  1142. }
  1143. else if (adj->adj_state == ISIS_ADJ_UP)
  1144. {
  1145. isis_adj_state_change (adj, ISIS_ADJ_INITIALIZING,
  1146. "no LAN Neighbours TLV found");
  1147. }
  1148. out:
  1149. if (isis->debugs & DEBUG_ADJ_PACKETS)
  1150. {
  1151. zlog_debug ("ISIS-Adj (%s): Rcvd L%d LAN IIH from %s on %s, cirType %s, "
  1152. "cirID %u, length %zd",
  1153. circuit->area->area_tag,
  1154. level, snpa_print (ssnpa), circuit->interface->name,
  1155. circuit_t2string (circuit->is_type),
  1156. circuit->circuit_id,
  1157. stream_get_endp (circuit->rcv_stream));
  1158. }
  1159. free_tlvs (&tlvs);
  1160. return retval;
  1161. }
  1162. /*
  1163. * Process Level 1/2 Link State
  1164. * ISO - 10589
  1165. * Section 7.3.15.1 - Action on receipt of a link state PDU
  1166. */
  1167. static int
  1168. process_lsp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
  1169. {
  1170. struct isis_link_state_hdr *hdr;
  1171. struct isis_adjacency *adj = NULL;
  1172. struct isis_lsp *lsp, *lsp0 = NULL;
  1173. int retval = ISIS_OK, comp = 0;
  1174. u_char lspid[ISIS_SYS_ID_LEN + 2];
  1175. struct isis_passwd *passwd;
  1176. uint16_t pdu_len;
  1177. if (isis->debugs & DEBUG_UPDATE_PACKETS)
  1178. {
  1179. zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP on %s, cirType %s, cirID %u",
  1180. circuit->area->area_tag, level, circuit->interface->name,
  1181. circuit_t2string (circuit->is_type), circuit->circuit_id);
  1182. if (isis->debugs & DEBUG_PACKET_DUMP)
  1183. zlog_dump_data (STREAM_DATA (circuit->rcv_stream),
  1184. stream_get_endp (circuit->rcv_stream));
  1185. }
  1186. if ((stream_get_endp (circuit->rcv_stream) -
  1187. stream_get_getp (circuit->rcv_stream)) < ISIS_LSP_HDR_LEN)
  1188. {
  1189. zlog_warn ("Packet too short");
  1190. return ISIS_WARNING;
  1191. }
  1192. /* Reference the header */
  1193. hdr = (struct isis_link_state_hdr *) STREAM_PNT (circuit->rcv_stream);
  1194. pdu_len = ntohs (hdr->pdu_len);
  1195. /* lsp length check */
  1196. if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_LSP_HDR_LEN) ||
  1197. pdu_len > ISO_MTU(circuit) ||
  1198. pdu_len > stream_get_endp (circuit->rcv_stream))
  1199. {
  1200. zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP length %d",
  1201. circuit->area->area_tag,
  1202. rawlspid_print (hdr->lsp_id), pdu_len);
  1203. return ISIS_WARNING;
  1204. }
  1205. /*
  1206. * Set the stream endp to PDU length, ignoring additional padding
  1207. * introduced by transport chips.
  1208. */
  1209. if (pdu_len < stream_get_endp (circuit->rcv_stream))
  1210. stream_set_endp (circuit->rcv_stream, pdu_len);
  1211. if (isis->debugs & DEBUG_UPDATE_PACKETS)
  1212. {
  1213. zlog_debug ("ISIS-Upd (%s): Rcvd L%d LSP %s, seq 0x%08x, cksum 0x%04x, "
  1214. "lifetime %us, len %u, on %s",
  1215. circuit->area->area_tag,
  1216. level,
  1217. rawlspid_print (hdr->lsp_id),
  1218. ntohl (hdr->seq_num),
  1219. ntohs (hdr->checksum),
  1220. ntohs (hdr->rem_lifetime),
  1221. pdu_len,
  1222. circuit->interface->name);
  1223. }
  1224. /* lsp is_type check */
  1225. if ((hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1 &&
  1226. (hdr->lsp_bits & IS_LEVEL_1_AND_2) != IS_LEVEL_1_AND_2)
  1227. {
  1228. zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP is type %x",
  1229. circuit->area->area_tag,
  1230. rawlspid_print (hdr->lsp_id), hdr->lsp_bits);
  1231. /* continue as per RFC1122 Be liberal in what you accept, and
  1232. * conservative in what you send */
  1233. }
  1234. /* Checksum sanity check - FIXME: move to correct place */
  1235. /* 12 = sysid+pdu+remtime */
  1236. if (iso_csum_verify (STREAM_PNT (circuit->rcv_stream) + 4,
  1237. pdu_len - 12, &hdr->checksum))
  1238. {
  1239. zlog_debug ("ISIS-Upd (%s): LSP %s invalid LSP checksum 0x%04x",
  1240. circuit->area->area_tag,
  1241. rawlspid_print (hdr->lsp_id), ntohs (hdr->checksum));
  1242. return ISIS_WARNING;
  1243. }
  1244. /* 7.3.15.1 a) 1 - external domain circuit will discard lsps */
  1245. if (circuit->ext_domain)
  1246. {
  1247. zlog_debug
  1248. ("ISIS-Upd (%s): LSP %s received at level %d over circuit with "
  1249. "externalDomain = true", circuit->area->area_tag,
  1250. rawlspid_print (hdr->lsp_id), level);
  1251. return ISIS_WARNING;
  1252. }
  1253. /* 7.3.15.1 a) 2,3 - manualL2OnlyMode not implemented */
  1254. if (!accept_level (level, circuit->is_type))
  1255. {
  1256. zlog_debug ("ISIS-Upd (%s): LSP %s received at level %d over circuit of"
  1257. " type %s",
  1258. circuit->area->area_tag,
  1259. rawlspid_print (hdr->lsp_id),
  1260. level, circuit_t2string (circuit->is_type));
  1261. return ISIS_WARNING;
  1262. }
  1263. /* 7.3.15.1 a) 4 - need to make sure IDLength matches */
  1264. /* 7.3.15.1 a) 5 - maximum area match, can be ommited since we only use 3 */
  1265. /* 7.3.15.1 a) 7 - password check */
  1266. (level == IS_LEVEL_1) ? (passwd = &circuit->area->area_passwd) :
  1267. (passwd = &circuit->area->domain_passwd);
  1268. if (passwd->type)
  1269. {
  1270. if (lsp_authentication_check (circuit->rcv_stream, circuit->area,
  1271. level, passwd))
  1272. {
  1273. isis_event_auth_failure (circuit->area->area_tag,
  1274. "LSP authentication failure", hdr->lsp_id);
  1275. return ISIS_WARNING;
  1276. }
  1277. }
  1278. /* Find the LSP in our database and compare it to this Link State header */
  1279. lsp = lsp_search (hdr->lsp_id, circuit->area->lspdb[level - 1]);
  1280. if (lsp)
  1281. comp = lsp_compare (circuit->area->area_tag, lsp, hdr->seq_num,
  1282. hdr->checksum, hdr->rem_lifetime);
  1283. if (lsp && (lsp->own_lsp
  1284. #ifdef TOPOLOGY_GENERATE
  1285. || lsp->from_topology
  1286. #endif /* TOPOLOGY_GENERATE */
  1287. ))
  1288. goto dontcheckadj;
  1289. /* 7.3.15.1 a) 6 - Must check that we have an adjacency of the same level */
  1290. /* for broadcast circuits, snpa should be compared */
  1291. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  1292. {
  1293. adj = isis_adj_lookup_snpa (ssnpa, circuit->u.bc.adjdb[level - 1]);
  1294. if (!adj)
  1295. {
  1296. zlog_debug ("(%s): DS ======= LSP %s, seq 0x%08x, cksum 0x%04x, "
  1297. "lifetime %us on %s",
  1298. circuit->area->area_tag,
  1299. rawlspid_print (hdr->lsp_id),
  1300. ntohl (hdr->seq_num),
  1301. ntohs (hdr->checksum),
  1302. ntohs (hdr->rem_lifetime), circuit->interface->name);
  1303. return ISIS_WARNING; /* Silently discard */
  1304. }
  1305. }
  1306. /* for non broadcast, we just need to find same level adj */
  1307. else
  1308. {
  1309. /* If no adj, or no sharing of level */
  1310. if (!circuit->u.p2p.neighbor)
  1311. {
  1312. return ISIS_OK; /* Silently discard */
  1313. }
  1314. else
  1315. {
  1316. if (((level == IS_LEVEL_1) &&
  1317. (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL2)) ||
  1318. ((level == IS_LEVEL_2) &&
  1319. (circuit->u.p2p.neighbor->adj_usage == ISIS_ADJ_LEVEL1)))
  1320. return ISIS_WARNING; /* Silently discard */
  1321. adj = circuit->u.p2p.neighbor;
  1322. }
  1323. }
  1324. dontcheckadj:
  1325. /* 7.3.15.1 a) 7 - Passwords for level 1 - not implemented */
  1326. /* 7.3.15.1 a) 8 - Passwords for level 2 - not implemented */
  1327. /* 7.3.15.1 a) 9 - OriginatingLSPBufferSize - not implemented FIXME: do it */
  1328. /* 7.3.15.1 b) - If the remaining life time is 0, we perform 7.3.16.4 */
  1329. if (hdr->rem_lifetime == 0)
  1330. {
  1331. if (!lsp)
  1332. {
  1333. /* 7.3.16.4 a) 1) No LSP in db -> send an ack, but don't save */
  1334. /* only needed on explicit update, eg - p2p */
  1335. if (circuit->circ_type == CIRCUIT_T_P2P)
  1336. ack_lsp (hdr, circuit, level);
  1337. return retval; /* FIXME: do we need a purge? */
  1338. }
  1339. else
  1340. {
  1341. if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
  1342. {
  1343. /* LSP by some other system -> do 7.3.16.4 b) */
  1344. /* 7.3.16.4 b) 1) */
  1345. if (comp == LSP_NEWER)
  1346. {
  1347. lsp_update (lsp, circuit->rcv_stream, circuit->area, level);
  1348. /* ii */
  1349. lsp_set_all_srmflags (lsp);
  1350. /* iii */
  1351. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1352. /* v */
  1353. ISIS_FLAGS_CLEAR_ALL (lsp->SSNflags); /* FIXME: OTHER than c */
  1354. /* iv */
  1355. if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  1356. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1357. } /* 7.3.16.4 b) 2) */
  1358. else if (comp == LSP_EQUAL)
  1359. {
  1360. /* i */
  1361. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1362. /* ii */
  1363. if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  1364. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1365. } /* 7.3.16.4 b) 3) */
  1366. else
  1367. {
  1368. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1369. ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
  1370. }
  1371. }
  1372. else if (lsp->lsp_header->rem_lifetime != 0)
  1373. {
  1374. /* our own LSP -> 7.3.16.4 c) */
  1375. if (comp == LSP_NEWER)
  1376. {
  1377. lsp_inc_seqnum (lsp, ntohl (hdr->seq_num));
  1378. lsp_set_all_srmflags (lsp);
  1379. }
  1380. else
  1381. {
  1382. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1383. ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
  1384. }
  1385. if (isis->debugs & DEBUG_UPDATE_PACKETS)
  1386. zlog_debug ("ISIS-Upd (%s): (1) re-originating LSP %s new "
  1387. "seq 0x%08x", circuit->area->area_tag,
  1388. rawlspid_print (hdr->lsp_id),
  1389. ntohl (lsp->lsp_header->seq_num));
  1390. }
  1391. }
  1392. return retval;
  1393. }
  1394. /* 7.3.15.1 c) - If this is our own lsp and we don't have it initiate a
  1395. * purge */
  1396. if (memcmp (hdr->lsp_id, isis->sysid, ISIS_SYS_ID_LEN) == 0)
  1397. {
  1398. if (!lsp)
  1399. {
  1400. /* 7.3.16.4: initiate a purge */
  1401. lsp_purge_non_exist(level, hdr, circuit->area);
  1402. return ISIS_OK;
  1403. }
  1404. /* 7.3.15.1 d) - If this is our own lsp and we have it */
  1405. /* In 7.3.16.1, If an Intermediate system R somewhere in the domain
  1406. * has information that the current sequence number for source S is
  1407. * "greater" than that held by S, ... */
  1408. if (ntohl (hdr->seq_num) > ntohl (lsp->lsp_header->seq_num))
  1409. {
  1410. /* 7.3.16.1 */
  1411. lsp_inc_seqnum (lsp, ntohl (hdr->seq_num));
  1412. if (isis->debugs & DEBUG_UPDATE_PACKETS)
  1413. zlog_debug ("ISIS-Upd (%s): (2) re-originating LSP %s new seq "
  1414. "0x%08x", circuit->area->area_tag,
  1415. rawlspid_print (hdr->lsp_id),
  1416. ntohl (lsp->lsp_header->seq_num));
  1417. }
  1418. /* If the received LSP is older or equal,
  1419. * resend the LSP which will act as ACK */
  1420. lsp_set_all_srmflags (lsp);
  1421. }
  1422. else
  1423. {
  1424. /* 7.3.15.1 e) - This lsp originated on another system */
  1425. /* 7.3.15.1 e) 1) LSP newer than the one in db or no LSP in db */
  1426. if ((!lsp || comp == LSP_NEWER))
  1427. {
  1428. /*
  1429. * If this lsp is a frag, need to see if we have zero lsp present
  1430. */
  1431. if (LSP_FRAGMENT (hdr->lsp_id) != 0)
  1432. {
  1433. memcpy (lspid, hdr->lsp_id, ISIS_SYS_ID_LEN + 1);
  1434. LSP_FRAGMENT (lspid) = 0;
  1435. lsp0 = lsp_search (lspid, circuit->area->lspdb[level - 1]);
  1436. if (!lsp0)
  1437. {
  1438. zlog_debug ("Got lsp frag, while zero lsp not in database");
  1439. return ISIS_OK;
  1440. }
  1441. }
  1442. /* i */
  1443. if (!lsp)
  1444. {
  1445. lsp = lsp_new_from_stream_ptr (circuit->rcv_stream,
  1446. pdu_len, lsp0,
  1447. circuit->area, level);
  1448. lsp_insert (lsp, circuit->area->lspdb[level - 1]);
  1449. }
  1450. else /* exists, so we overwrite */
  1451. {
  1452. lsp_update (lsp, circuit->rcv_stream, circuit->area, level);
  1453. }
  1454. /* ii */
  1455. lsp_set_all_srmflags (lsp);
  1456. /* iii */
  1457. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1458. /* iv */
  1459. if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  1460. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1461. /* FIXME: v) */
  1462. }
  1463. /* 7.3.15.1 e) 2) LSP equal to the one in db */
  1464. else if (comp == LSP_EQUAL)
  1465. {
  1466. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1467. lsp_update (lsp, circuit->rcv_stream, circuit->area, level);
  1468. if (circuit->circ_type != CIRCUIT_T_BROADCAST)
  1469. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1470. }
  1471. /* 7.3.15.1 e) 3) LSP older than the one in db */
  1472. else
  1473. {
  1474. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1475. ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
  1476. }
  1477. }
  1478. return retval;
  1479. }
  1480. /*
  1481. * Process Sequence Numbers
  1482. * ISO - 10589
  1483. * Section 7.3.15.2 - Action on receipt of a sequence numbers PDU
  1484. */
  1485. static int
  1486. process_snp (int snp_type, int level, struct isis_circuit *circuit,
  1487. const u_char *ssnpa)
  1488. {
  1489. int retval = ISIS_OK;
  1490. int cmp, own_lsp;
  1491. char typechar = ' ';
  1492. uint16_t pdu_len;
  1493. struct isis_adjacency *adj;
  1494. struct isis_complete_seqnum_hdr *chdr = NULL;
  1495. struct isis_partial_seqnum_hdr *phdr = NULL;
  1496. uint32_t found = 0, expected = 0, auth_tlv_offset = 0;
  1497. struct isis_lsp *lsp;
  1498. struct lsp_entry *entry;
  1499. struct listnode *node, *nnode;
  1500. struct listnode *node2, *nnode2;
  1501. struct tlvs tlvs;
  1502. struct list *lsp_list = NULL;
  1503. struct isis_passwd *passwd;
  1504. if (snp_type == ISIS_SNP_CSNP_FLAG)
  1505. {
  1506. /* getting the header info */
  1507. typechar = 'C';
  1508. chdr =
  1509. (struct isis_complete_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
  1510. stream_forward_getp (circuit->rcv_stream, ISIS_CSNP_HDRLEN);
  1511. pdu_len = ntohs (chdr->pdu_len);
  1512. if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_CSNP_HDRLEN) ||
  1513. pdu_len > ISO_MTU(circuit) ||
  1514. pdu_len > stream_get_endp (circuit->rcv_stream))
  1515. {
  1516. zlog_warn ("Received a CSNP with bogus length %d", pdu_len);
  1517. return ISIS_WARNING;
  1518. }
  1519. }
  1520. else
  1521. {
  1522. typechar = 'P';
  1523. phdr =
  1524. (struct isis_partial_seqnum_hdr *) STREAM_PNT (circuit->rcv_stream);
  1525. stream_forward_getp (circuit->rcv_stream, ISIS_PSNP_HDRLEN);
  1526. pdu_len = ntohs (phdr->pdu_len);
  1527. if (pdu_len < (ISIS_FIXED_HDR_LEN + ISIS_PSNP_HDRLEN) ||
  1528. pdu_len > ISO_MTU(circuit) ||
  1529. pdu_len > stream_get_endp (circuit->rcv_stream))
  1530. {
  1531. zlog_warn ("Received a PSNP with bogus length %d", pdu_len);
  1532. return ISIS_WARNING;
  1533. }
  1534. }
  1535. /*
  1536. * Set the stream endp to PDU length, ignoring additional padding
  1537. * introduced by transport chips.
  1538. */
  1539. if (pdu_len < stream_get_endp (circuit->rcv_stream))
  1540. stream_set_endp (circuit->rcv_stream, pdu_len);
  1541. /* 7.3.15.2 a) 1 - external domain circuit will discard snp pdu */
  1542. if (circuit->ext_domain)
  1543. {
  1544. zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
  1545. "skipping: circuit externalDomain = true",
  1546. circuit->area->area_tag,
  1547. level, typechar, circuit->interface->name);
  1548. return ISIS_OK;
  1549. }
  1550. /* 7.3.15.2 a) 2,3 - manualL2OnlyMode not implemented */
  1551. if (!accept_level (level, circuit->is_type))
  1552. {
  1553. zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP on %s, "
  1554. "skipping: circuit type %s does not match level %d",
  1555. circuit->area->area_tag,
  1556. level,
  1557. typechar,
  1558. circuit->interface->name,
  1559. circuit_t2string (circuit->is_type), level);
  1560. return ISIS_OK;
  1561. }
  1562. /* 7.3.15.2 a) 4 - not applicable for CSNP only PSNPs on broadcast */
  1563. if ((snp_type == ISIS_SNP_PSNP_FLAG) &&
  1564. (circuit->circ_type == CIRCUIT_T_BROADCAST) &&
  1565. (!circuit->u.bc.is_dr[level - 1]))
  1566. {
  1567. zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s, "
  1568. "skipping: we are not the DIS",
  1569. circuit->area->area_tag,
  1570. level,
  1571. typechar, snpa_print (ssnpa), circuit->interface->name);
  1572. return ISIS_OK;
  1573. }
  1574. /* 7.3.15.2 a) 5 - need to make sure IDLength matches - already checked */
  1575. /* 7.3.15.2 a) 6 - maximum area match, can be ommited since we only use 3
  1576. * - already checked */
  1577. /* 7.3.15.2 a) 7 - Must check that we have an adjacency of the same level */
  1578. /* for broadcast circuits, snpa should be compared */
  1579. /* FIXME : Do we need to check SNPA? */
  1580. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  1581. {
  1582. if (snp_type == ISIS_SNP_CSNP_FLAG)
  1583. {
  1584. adj =
  1585. isis_adj_lookup (chdr->source_id, circuit->u.bc.adjdb[level - 1]);
  1586. }
  1587. else
  1588. {
  1589. /* a psnp on a broadcast, how lovely of Juniper :) */
  1590. adj =
  1591. isis_adj_lookup (phdr->source_id, circuit->u.bc.adjdb[level - 1]);
  1592. }
  1593. if (!adj)
  1594. return ISIS_OK; /* Silently discard */
  1595. }
  1596. else
  1597. {
  1598. if (!circuit->u.p2p.neighbor)
  1599. {
  1600. zlog_warn ("no p2p neighbor on circuit %s", circuit->interface->name);
  1601. return ISIS_OK; /* Silently discard */
  1602. }
  1603. }
  1604. /* 7.3.15.2 a) 8 - Passwords for level 1 - not implemented */
  1605. /* 7.3.15.2 a) 9 - Passwords for level 2 - not implemented */
  1606. memset (&tlvs, 0, sizeof (struct tlvs));
  1607. /* parse the SNP */
  1608. expected |= TLVFLAG_LSP_ENTRIES;
  1609. expected |= TLVFLAG_AUTH_INFO;
  1610. auth_tlv_offset = stream_get_getp (circuit->rcv_stream);
  1611. retval = parse_tlvs (circuit->area->area_tag,
  1612. STREAM_PNT (circuit->rcv_stream),
  1613. pdu_len - stream_get_getp (circuit->rcv_stream),
  1614. &expected, &found, &tlvs, &auth_tlv_offset);
  1615. if (retval > ISIS_WARNING)
  1616. {
  1617. zlog_warn ("something went very wrong processing SNP");
  1618. free_tlvs (&tlvs);
  1619. return retval;
  1620. }
  1621. if (level == IS_LEVEL_1)
  1622. passwd = &circuit->area->area_passwd;
  1623. else
  1624. passwd = &circuit->area->domain_passwd;
  1625. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_RECV))
  1626. {
  1627. if (passwd->type)
  1628. {
  1629. if (!(found & TLVFLAG_AUTH_INFO) ||
  1630. authentication_check (&tlvs.auth_info, passwd,
  1631. circuit->rcv_stream, auth_tlv_offset))
  1632. {
  1633. isis_event_auth_failure (circuit->area->area_tag,
  1634. "SNP authentication" " failure",
  1635. phdr ? phdr->source_id :
  1636. chdr->source_id);
  1637. free_tlvs (&tlvs);
  1638. return ISIS_OK;
  1639. }
  1640. }
  1641. }
  1642. /* debug isis snp-packets */
  1643. if (isis->debugs & DEBUG_SNP_PACKETS)
  1644. {
  1645. zlog_debug ("ISIS-Snp (%s): Rcvd L%d %cSNP from %s on %s",
  1646. circuit->area->area_tag,
  1647. level,
  1648. typechar, snpa_print (ssnpa), circuit->interface->name);
  1649. if (tlvs.lsp_entries)
  1650. {
  1651. for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
  1652. {
  1653. zlog_debug ("ISIS-Snp (%s): %cSNP entry %s, seq 0x%08x,"
  1654. " cksum 0x%04x, lifetime %us",
  1655. circuit->area->area_tag,
  1656. typechar,
  1657. rawlspid_print (entry->lsp_id),
  1658. ntohl (entry->seq_num),
  1659. ntohs (entry->checksum), ntohs (entry->rem_lifetime));
  1660. }
  1661. }
  1662. }
  1663. /* 7.3.15.2 b) Actions on LSP_ENTRIES reported */
  1664. if (tlvs.lsp_entries)
  1665. {
  1666. for (ALL_LIST_ELEMENTS_RO (tlvs.lsp_entries, node, entry))
  1667. {
  1668. lsp = lsp_search (entry->lsp_id, circuit->area->lspdb[level - 1]);
  1669. own_lsp = !memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN);
  1670. if (lsp)
  1671. {
  1672. /* 7.3.15.2 b) 1) is this LSP newer */
  1673. cmp = lsp_compare (circuit->area->area_tag, lsp, entry->seq_num,
  1674. entry->checksum, entry->rem_lifetime);
  1675. /* 7.3.15.2 b) 2) if it equals, clear SRM on p2p */
  1676. if (cmp == LSP_EQUAL)
  1677. {
  1678. /* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */
  1679. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1680. }
  1681. /* 7.3.15.2 b) 3) if it is older, clear SSN and set SRM */
  1682. else if (cmp == LSP_OLDER)
  1683. {
  1684. ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
  1685. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1686. }
  1687. /* 7.3.15.2 b) 4) if it is newer, set SSN and clear SRM on p2p */
  1688. else
  1689. {
  1690. if (own_lsp)
  1691. {
  1692. lsp_inc_seqnum (lsp, ntohl (entry->seq_num));
  1693. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1694. }
  1695. else
  1696. {
  1697. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1698. /* if (circuit->circ_type != CIRCUIT_T_BROADCAST) */
  1699. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  1700. }
  1701. }
  1702. }
  1703. else
  1704. {
  1705. /* 7.3.15.2 b) 5) if it was not found, and all of those are not 0,
  1706. * insert it and set SSN on it */
  1707. if (entry->rem_lifetime && entry->checksum && entry->seq_num &&
  1708. memcmp (entry->lsp_id, isis->sysid, ISIS_SYS_ID_LEN))
  1709. {
  1710. lsp = lsp_new(circuit->area, entry->lsp_id,
  1711. ntohs(entry->rem_lifetime),
  1712. 0, 0, entry->checksum, level);
  1713. lsp_insert (lsp, circuit->area->lspdb[level - 1]);
  1714. ISIS_FLAGS_CLEAR_ALL (lsp->SRMflags);
  1715. ISIS_SET_FLAG (lsp->SSNflags, circuit);
  1716. }
  1717. }
  1718. }
  1719. }
  1720. /* 7.3.15.2 c) on CSNP set SRM for all in range which were not reported */
  1721. if (snp_type == ISIS_SNP_CSNP_FLAG)
  1722. {
  1723. /*
  1724. * Build a list from our own LSP db bounded with
  1725. * start_lsp_id and stop_lsp_id
  1726. */
  1727. lsp_list = list_new ();
  1728. lsp_build_list_nonzero_ht (chdr->start_lsp_id, chdr->stop_lsp_id,
  1729. lsp_list, circuit->area->lspdb[level - 1]);
  1730. /* Fixme: Find a better solution */
  1731. if (tlvs.lsp_entries)
  1732. {
  1733. for (ALL_LIST_ELEMENTS (tlvs.lsp_entries, node, nnode, entry))
  1734. {
  1735. for (ALL_LIST_ELEMENTS (lsp_list, node2, nnode2, lsp))
  1736. {
  1737. if (lsp_id_cmp (lsp->lsp_header->lsp_id, entry->lsp_id) == 0)
  1738. {
  1739. list_delete_node (lsp_list, node2);
  1740. break;
  1741. }
  1742. }
  1743. }
  1744. }
  1745. /* on remaining LSPs we set SRM (neighbor knew not of) */
  1746. for (ALL_LIST_ELEMENTS_RO (lsp_list, node, lsp))
  1747. ISIS_SET_FLAG (lsp->SRMflags, circuit);
  1748. /* lets free it */
  1749. list_delete (lsp_list);
  1750. }
  1751. free_tlvs (&tlvs);
  1752. return retval;
  1753. }
  1754. static int
  1755. process_csnp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
  1756. {
  1757. if (isis->debugs & DEBUG_SNP_PACKETS)
  1758. {
  1759. zlog_debug ("ISIS-Snp (%s): Rcvd L%d CSNP on %s, cirType %s, cirID %u",
  1760. circuit->area->area_tag, level, circuit->interface->name,
  1761. circuit_t2string (circuit->is_type), circuit->circuit_id);
  1762. if (isis->debugs & DEBUG_PACKET_DUMP)
  1763. zlog_dump_data (STREAM_DATA (circuit->rcv_stream),
  1764. stream_get_endp (circuit->rcv_stream));
  1765. }
  1766. /* Sanity check - FIXME: move to correct place */
  1767. if ((stream_get_endp (circuit->rcv_stream) -
  1768. stream_get_getp (circuit->rcv_stream)) < ISIS_CSNP_HDRLEN)
  1769. {
  1770. zlog_warn ("Packet too short ( < %d)", ISIS_CSNP_HDRLEN);
  1771. return ISIS_WARNING;
  1772. }
  1773. return process_snp (ISIS_SNP_CSNP_FLAG, level, circuit, ssnpa);
  1774. }
  1775. static int
  1776. process_psnp (int level, struct isis_circuit *circuit, const u_char *ssnpa)
  1777. {
  1778. if (isis->debugs & DEBUG_SNP_PACKETS)
  1779. {
  1780. zlog_debug ("ISIS-Snp (%s): Rcvd L%d PSNP on %s, cirType %s, cirID %u",
  1781. circuit->area->area_tag, level, circuit->interface->name,
  1782. circuit_t2string (circuit->is_type), circuit->circuit_id);
  1783. if (isis->debugs & DEBUG_PACKET_DUMP)
  1784. zlog_dump_data (STREAM_DATA (circuit->rcv_stream),
  1785. stream_get_endp (circuit->rcv_stream));
  1786. }
  1787. if ((stream_get_endp (circuit->rcv_stream) -
  1788. stream_get_getp (circuit->rcv_stream)) < ISIS_PSNP_HDRLEN)
  1789. {
  1790. zlog_warn ("Packet too short ( < %d)", ISIS_PSNP_HDRLEN);
  1791. return ISIS_WARNING;
  1792. }
  1793. return process_snp (ISIS_SNP_PSNP_FLAG, level, circuit, ssnpa);
  1794. }
  1795. /*
  1796. * PDU Dispatcher
  1797. */
  1798. static int
  1799. isis_handle_pdu (struct isis_circuit *circuit, u_char * ssnpa)
  1800. {
  1801. struct isis_fixed_hdr *hdr;
  1802. int retval = ISIS_OK;
  1803. /*
  1804. * Let's first read data from stream to the header
  1805. */
  1806. hdr = (struct isis_fixed_hdr *) STREAM_DATA (circuit->rcv_stream);
  1807. if ((hdr->idrp != ISO10589_ISIS) && (hdr->idrp != ISO9542_ESIS))
  1808. {
  1809. zlog_err ("Not an IS-IS or ES-IS packet IDRP=%02x", hdr->idrp);
  1810. return ISIS_ERROR;
  1811. }
  1812. /* now we need to know if this is an ISO 9542 packet and
  1813. * take real good care of it, waaa!
  1814. */
  1815. if (hdr->idrp == ISO9542_ESIS)
  1816. {
  1817. zlog_err ("No support for ES-IS packet IDRP=%02x", hdr->idrp);
  1818. return ISIS_ERROR;
  1819. }
  1820. stream_set_getp (circuit->rcv_stream, ISIS_FIXED_HDR_LEN);
  1821. /*
  1822. * and then process it
  1823. */
  1824. if (hdr->length < ISIS_MINIMUM_FIXED_HDR_LEN)
  1825. {
  1826. zlog_err ("Fixed header length = %d", hdr->length);
  1827. return ISIS_ERROR;
  1828. }
  1829. if (hdr->version1 != 1)
  1830. {
  1831. zlog_warn ("Unsupported ISIS version %u", hdr->version1);
  1832. return ISIS_WARNING;
  1833. }
  1834. /* either 6 or 0 */
  1835. if ((hdr->id_len != 0) && (hdr->id_len != ISIS_SYS_ID_LEN))
  1836. {
  1837. zlog_err
  1838. ("IDFieldLengthMismatch: ID Length field in a received PDU %u, "
  1839. "while the parameter for this IS is %u", hdr->id_len,
  1840. ISIS_SYS_ID_LEN);
  1841. return ISIS_ERROR;
  1842. }
  1843. if (hdr->version2 != 1)
  1844. {
  1845. zlog_warn ("Unsupported ISIS version %u", hdr->version2);
  1846. return ISIS_WARNING;
  1847. }
  1848. if (circuit->is_passive)
  1849. {
  1850. zlog_warn ("Received ISIS PDU on passive circuit %s",
  1851. circuit->interface->name);
  1852. return ISIS_WARNING;
  1853. }
  1854. /* either 3 or 0 */
  1855. if ((hdr->max_area_addrs != 0)
  1856. && (hdr->max_area_addrs != isis->max_area_addrs))
  1857. {
  1858. zlog_err ("maximumAreaAddressesMismatch: maximumAreaAdresses in a "
  1859. "received PDU %u while the parameter for this IS is %u",
  1860. hdr->max_area_addrs, isis->max_area_addrs);
  1861. return ISIS_ERROR;
  1862. }
  1863. switch (hdr->pdu_type)
  1864. {
  1865. case L1_LAN_HELLO:
  1866. retval = process_lan_hello (ISIS_LEVEL1, circuit, ssnpa);
  1867. break;
  1868. case L2_LAN_HELLO:
  1869. retval = process_lan_hello (ISIS_LEVEL2, circuit, ssnpa);
  1870. break;
  1871. case P2P_HELLO:
  1872. retval = process_p2p_hello (circuit);
  1873. break;
  1874. case L1_LINK_STATE:
  1875. retval = process_lsp (ISIS_LEVEL1, circuit, ssnpa);
  1876. break;
  1877. case L2_LINK_STATE:
  1878. retval = process_lsp (ISIS_LEVEL2, circuit, ssnpa);
  1879. break;
  1880. case L1_COMPLETE_SEQ_NUM:
  1881. retval = process_csnp (ISIS_LEVEL1, circuit, ssnpa);
  1882. break;
  1883. case L2_COMPLETE_SEQ_NUM:
  1884. retval = process_csnp (ISIS_LEVEL2, circuit, ssnpa);
  1885. break;
  1886. case L1_PARTIAL_SEQ_NUM:
  1887. retval = process_psnp (ISIS_LEVEL1, circuit, ssnpa);
  1888. break;
  1889. case L2_PARTIAL_SEQ_NUM:
  1890. retval = process_psnp (ISIS_LEVEL2, circuit, ssnpa);
  1891. break;
  1892. default:
  1893. return ISIS_ERROR;
  1894. }
  1895. return retval;
  1896. }
  1897. #ifdef GNU_LINUX
  1898. int
  1899. isis_receive (struct thread *thread)
  1900. {
  1901. struct isis_circuit *circuit;
  1902. u_char ssnpa[ETH_ALEN];
  1903. int retval;
  1904. /*
  1905. * Get the circuit
  1906. */
  1907. circuit = THREAD_ARG (thread);
  1908. assert (circuit);
  1909. isis_circuit_stream(circuit, &circuit->rcv_stream);
  1910. retval = circuit->rx (circuit, ssnpa);
  1911. circuit->t_read = NULL;
  1912. if (retval == ISIS_OK)
  1913. retval = isis_handle_pdu (circuit, ssnpa);
  1914. /*
  1915. * prepare for next packet.
  1916. */
  1917. if (!circuit->is_passive)
  1918. {
  1919. THREAD_READ_ON (master, circuit->t_read, isis_receive, circuit,
  1920. circuit->fd);
  1921. }
  1922. return retval;
  1923. }
  1924. #else
  1925. int
  1926. isis_receive (struct thread *thread)
  1927. {
  1928. struct isis_circuit *circuit;
  1929. u_char ssnpa[ETH_ALEN];
  1930. int retval;
  1931. /*
  1932. * Get the circuit
  1933. */
  1934. circuit = THREAD_ARG (thread);
  1935. assert (circuit);
  1936. circuit->t_read = NULL;
  1937. isis_circuit_stream(circuit, &circuit->rcv_stream);
  1938. retval = circuit->rx (circuit, ssnpa);
  1939. if (retval == ISIS_OK)
  1940. retval = isis_handle_pdu (circuit, ssnpa);
  1941. /*
  1942. * prepare for next packet.
  1943. */
  1944. if (!circuit->is_passive)
  1945. {
  1946. circuit->t_read = thread_add_timer_msec (master, isis_receive, circuit,
  1947. listcount
  1948. (circuit->area->circuit_list) *
  1949. 100);
  1950. }
  1951. return retval;
  1952. }
  1953. #endif
  1954. /* filling of the fixed isis header */
  1955. void
  1956. fill_fixed_hdr (struct isis_fixed_hdr *hdr, u_char pdu_type)
  1957. {
  1958. memset (hdr, 0, sizeof (struct isis_fixed_hdr));
  1959. hdr->idrp = ISO10589_ISIS;
  1960. switch (pdu_type)
  1961. {
  1962. case L1_LAN_HELLO:
  1963. case L2_LAN_HELLO:
  1964. hdr->length = ISIS_LANHELLO_HDRLEN;
  1965. break;
  1966. case P2P_HELLO:
  1967. hdr->length = ISIS_P2PHELLO_HDRLEN;
  1968. break;
  1969. case L1_LINK_STATE:
  1970. case L2_LINK_STATE:
  1971. hdr->length = ISIS_LSP_HDR_LEN;
  1972. break;
  1973. case L1_COMPLETE_SEQ_NUM:
  1974. case L2_COMPLETE_SEQ_NUM:
  1975. hdr->length = ISIS_CSNP_HDRLEN;
  1976. break;
  1977. case L1_PARTIAL_SEQ_NUM:
  1978. case L2_PARTIAL_SEQ_NUM:
  1979. hdr->length = ISIS_PSNP_HDRLEN;
  1980. break;
  1981. default:
  1982. zlog_warn ("fill_fixed_hdr(): unknown pdu type %d", pdu_type);
  1983. return;
  1984. }
  1985. hdr->length += ISIS_FIXED_HDR_LEN;
  1986. hdr->pdu_type = pdu_type;
  1987. hdr->version1 = 1;
  1988. hdr->id_len = 0; /* ISIS_SYS_ID_LEN - 0==6 */
  1989. hdr->version2 = 1;
  1990. hdr->max_area_addrs = 0; /* isis->max_area_addrs - 0==3 */
  1991. }
  1992. /*
  1993. * SEND SIDE
  1994. */
  1995. static void
  1996. fill_fixed_hdr_andstream (struct isis_fixed_hdr *hdr, u_char pdu_type,
  1997. struct stream *stream)
  1998. {
  1999. fill_fixed_hdr (hdr, pdu_type);
  2000. stream_putc (stream, hdr->idrp);
  2001. stream_putc (stream, hdr->length);
  2002. stream_putc (stream, hdr->version1);
  2003. stream_putc (stream, hdr->id_len);
  2004. stream_putc (stream, hdr->pdu_type);
  2005. stream_putc (stream, hdr->version2);
  2006. stream_putc (stream, hdr->reserved);
  2007. stream_putc (stream, hdr->max_area_addrs);
  2008. return;
  2009. }
  2010. int
  2011. send_hello (struct isis_circuit *circuit, int level)
  2012. {
  2013. struct isis_fixed_hdr fixed_hdr;
  2014. struct isis_lan_hello_hdr hello_hdr;
  2015. struct isis_p2p_hello_hdr p2p_hello_hdr;
  2016. unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
  2017. size_t len_pointer, length, auth_tlv_offset = 0;
  2018. u_int32_t interval;
  2019. int retval;
  2020. if (circuit->is_passive)
  2021. return ISIS_OK;
  2022. if (circuit->interface->mtu == 0)
  2023. {
  2024. zlog_warn ("circuit has zero MTU");
  2025. return ISIS_WARNING;
  2026. }
  2027. isis_circuit_stream(circuit, &circuit->snd_stream);
  2028. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  2029. if (level == IS_LEVEL_1)
  2030. fill_fixed_hdr_andstream (&fixed_hdr, L1_LAN_HELLO,
  2031. circuit->snd_stream);
  2032. else
  2033. fill_fixed_hdr_andstream (&fixed_hdr, L2_LAN_HELLO,
  2034. circuit->snd_stream);
  2035. else
  2036. fill_fixed_hdr_andstream (&fixed_hdr, P2P_HELLO, circuit->snd_stream);
  2037. /*
  2038. * Fill LAN Level 1 or 2 Hello PDU header
  2039. */
  2040. memset (&hello_hdr, 0, sizeof (struct isis_lan_hello_hdr));
  2041. interval = circuit->hello_multiplier[level - 1] *
  2042. circuit->hello_interval[level - 1];
  2043. if (interval > USHRT_MAX)
  2044. interval = USHRT_MAX;
  2045. hello_hdr.circuit_t = circuit->is_type;
  2046. memcpy (hello_hdr.source_id, isis->sysid, ISIS_SYS_ID_LEN);
  2047. hello_hdr.hold_time = htons ((u_int16_t) interval);
  2048. hello_hdr.pdu_len = 0; /* Update the PDU Length later */
  2049. len_pointer = stream_get_endp (circuit->snd_stream) + 3 + ISIS_SYS_ID_LEN;
  2050. /* copy the shared part of the hello to the p2p hello if needed */
  2051. if (circuit->circ_type == CIRCUIT_T_P2P)
  2052. {
  2053. memcpy (&p2p_hello_hdr, &hello_hdr, 5 + ISIS_SYS_ID_LEN);
  2054. p2p_hello_hdr.local_id = circuit->circuit_id;
  2055. /* FIXME: need better understanding */
  2056. stream_put (circuit->snd_stream, &p2p_hello_hdr, ISIS_P2PHELLO_HDRLEN);
  2057. }
  2058. else
  2059. {
  2060. hello_hdr.prio = circuit->priority[level - 1];
  2061. if (level == IS_LEVEL_1)
  2062. {
  2063. memcpy (hello_hdr.lan_id, circuit->u.bc.l1_desig_is,
  2064. ISIS_SYS_ID_LEN + 1);
  2065. }
  2066. else if (level == IS_LEVEL_2)
  2067. {
  2068. memcpy (hello_hdr.lan_id, circuit->u.bc.l2_desig_is,
  2069. ISIS_SYS_ID_LEN + 1);
  2070. }
  2071. stream_put (circuit->snd_stream, &hello_hdr, ISIS_LANHELLO_HDRLEN);
  2072. }
  2073. /*
  2074. * Then the variable length part.
  2075. */
  2076. /* add circuit password */
  2077. switch (circuit->passwd.type)
  2078. {
  2079. /* Cleartext */
  2080. case ISIS_PASSWD_TYPE_CLEARTXT:
  2081. if (tlv_add_authinfo (circuit->passwd.type, circuit->passwd.len,
  2082. circuit->passwd.passwd, circuit->snd_stream))
  2083. return ISIS_WARNING;
  2084. break;
  2085. /* HMAC MD5 */
  2086. case ISIS_PASSWD_TYPE_HMAC_MD5:
  2087. /* Remember where TLV is written so we can later overwrite the MD5 hash */
  2088. auth_tlv_offset = stream_get_endp (circuit->snd_stream);
  2089. memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
  2090. if (tlv_add_authinfo (circuit->passwd.type, ISIS_AUTH_MD5_SIZE,
  2091. hmac_md5_hash, circuit->snd_stream))
  2092. return ISIS_WARNING;
  2093. break;
  2094. default:
  2095. break;
  2096. }
  2097. /* Area Addresses TLV */
  2098. if (listcount (circuit->area->area_addrs) == 0)
  2099. return ISIS_WARNING;
  2100. if (tlv_add_area_addrs (circuit->area->area_addrs, circuit->snd_stream))
  2101. return ISIS_WARNING;
  2102. /* LAN Neighbors TLV */
  2103. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  2104. {
  2105. if (level == IS_LEVEL_1 && circuit->u.bc.lan_neighs[0] &&
  2106. listcount (circuit->u.bc.lan_neighs[0]) > 0)
  2107. if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[0],
  2108. circuit->snd_stream))
  2109. return ISIS_WARNING;
  2110. if (level == IS_LEVEL_2 && circuit->u.bc.lan_neighs[1] &&
  2111. listcount (circuit->u.bc.lan_neighs[1]) > 0)
  2112. if (tlv_add_lan_neighs (circuit->u.bc.lan_neighs[1],
  2113. circuit->snd_stream))
  2114. return ISIS_WARNING;
  2115. }
  2116. /* Protocols Supported TLV */
  2117. if (circuit->nlpids.count > 0)
  2118. if (tlv_add_nlpid (&circuit->nlpids, circuit->snd_stream))
  2119. return ISIS_WARNING;
  2120. /* IP interface Address TLV */
  2121. if (circuit->ip_router && circuit->ip_addrs &&
  2122. listcount (circuit->ip_addrs) > 0)
  2123. if (tlv_add_ip_addrs (circuit->ip_addrs, circuit->snd_stream))
  2124. return ISIS_WARNING;
  2125. #ifdef HAVE_IPV6
  2126. /* IPv6 Interface Address TLV */
  2127. if (circuit->ipv6_router && circuit->ipv6_link &&
  2128. listcount (circuit->ipv6_link) > 0)
  2129. if (tlv_add_ipv6_addrs (circuit->ipv6_link, circuit->snd_stream))
  2130. return ISIS_WARNING;
  2131. #endif /* HAVE_IPV6 */
  2132. if (circuit->pad_hellos)
  2133. if (tlv_add_padding (circuit->snd_stream))
  2134. return ISIS_WARNING;
  2135. length = stream_get_endp (circuit->snd_stream);
  2136. /* Update PDU length */
  2137. stream_putw_at (circuit->snd_stream, len_pointer, (u_int16_t) length);
  2138. /* For HMAC MD5 we need to compute the md5 hash and store it */
  2139. if (circuit->passwd.type == ISIS_PASSWD_TYPE_HMAC_MD5)
  2140. {
  2141. hmac_md5 (STREAM_DATA (circuit->snd_stream),
  2142. stream_get_endp (circuit->snd_stream),
  2143. (unsigned char *) &circuit->passwd.passwd, circuit->passwd.len,
  2144. (unsigned char *) &hmac_md5_hash);
  2145. /* Copy the hash into the stream */
  2146. memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
  2147. hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
  2148. }
  2149. if (isis->debugs & DEBUG_ADJ_PACKETS)
  2150. {
  2151. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  2152. {
  2153. zlog_debug ("ISIS-Adj (%s): Sent L%d LAN IIH on %s, length %zd",
  2154. circuit->area->area_tag, level, circuit->interface->name,
  2155. length);
  2156. }
  2157. else
  2158. {
  2159. zlog_debug ("ISIS-Adj (%s): Sent P2P IIH on %s, length %zd",
  2160. circuit->area->area_tag, circuit->interface->name,
  2161. length);
  2162. }
  2163. if (isis->debugs & DEBUG_PACKET_DUMP)
  2164. zlog_dump_data (STREAM_DATA (circuit->snd_stream),
  2165. stream_get_endp (circuit->snd_stream));
  2166. }
  2167. retval = circuit->tx (circuit, level);
  2168. if (retval != ISIS_OK)
  2169. zlog_err ("ISIS-Adj (%s): Send L%d IIH on %s failed",
  2170. circuit->area->area_tag, level, circuit->interface->name);
  2171. return retval;
  2172. }
  2173. int
  2174. send_lan_l1_hello (struct thread *thread)
  2175. {
  2176. struct isis_circuit *circuit;
  2177. int retval;
  2178. circuit = THREAD_ARG (thread);
  2179. assert (circuit);
  2180. circuit->u.bc.t_send_lan_hello[0] = NULL;
  2181. if (!(circuit->area->is_type & IS_LEVEL_1))
  2182. {
  2183. zlog_warn ("ISIS-Hello (%s): Trying to send L1 IIH in L2-only area",
  2184. circuit->area->area_tag);
  2185. return 1;
  2186. }
  2187. if (circuit->u.bc.run_dr_elect[0])
  2188. retval = isis_dr_elect (circuit, 1);
  2189. retval = send_hello (circuit, 1);
  2190. /* set next timer thread */
  2191. THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[0],
  2192. send_lan_l1_hello, circuit,
  2193. isis_jitter (circuit->hello_interval[0], IIH_JITTER));
  2194. return retval;
  2195. }
  2196. int
  2197. send_lan_l2_hello (struct thread *thread)
  2198. {
  2199. struct isis_circuit *circuit;
  2200. int retval;
  2201. circuit = THREAD_ARG (thread);
  2202. assert (circuit);
  2203. circuit->u.bc.t_send_lan_hello[1] = NULL;
  2204. if (!(circuit->area->is_type & IS_LEVEL_2))
  2205. {
  2206. zlog_warn ("ISIS-Hello (%s): Trying to send L2 IIH in L1 area",
  2207. circuit->area->area_tag);
  2208. return 1;
  2209. }
  2210. if (circuit->u.bc.run_dr_elect[1])
  2211. retval = isis_dr_elect (circuit, 2);
  2212. retval = send_hello (circuit, 2);
  2213. /* set next timer thread */
  2214. THREAD_TIMER_ON (master, circuit->u.bc.t_send_lan_hello[1],
  2215. send_lan_l2_hello, circuit,
  2216. isis_jitter (circuit->hello_interval[1], IIH_JITTER));
  2217. return retval;
  2218. }
  2219. int
  2220. send_p2p_hello (struct thread *thread)
  2221. {
  2222. struct isis_circuit *circuit;
  2223. circuit = THREAD_ARG (thread);
  2224. assert (circuit);
  2225. circuit->u.p2p.t_send_p2p_hello = NULL;
  2226. send_hello (circuit, 1);
  2227. /* set next timer thread */
  2228. THREAD_TIMER_ON (master, circuit->u.p2p.t_send_p2p_hello, send_p2p_hello,
  2229. circuit, isis_jitter (circuit->hello_interval[1],
  2230. IIH_JITTER));
  2231. return ISIS_OK;
  2232. }
  2233. static int
  2234. build_csnp (int level, u_char * start, u_char * stop, struct list *lsps,
  2235. struct isis_circuit *circuit)
  2236. {
  2237. struct isis_fixed_hdr fixed_hdr;
  2238. struct isis_passwd *passwd;
  2239. unsigned long lenp;
  2240. u_int16_t length;
  2241. unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
  2242. unsigned long auth_tlv_offset = 0;
  2243. int retval = ISIS_OK;
  2244. isis_circuit_stream(circuit, &circuit->snd_stream);
  2245. if (level == IS_LEVEL_1)
  2246. fill_fixed_hdr_andstream (&fixed_hdr, L1_COMPLETE_SEQ_NUM,
  2247. circuit->snd_stream);
  2248. else
  2249. fill_fixed_hdr_andstream (&fixed_hdr, L2_COMPLETE_SEQ_NUM,
  2250. circuit->snd_stream);
  2251. /*
  2252. * Fill Level 1 or 2 Complete Sequence Numbers header
  2253. */
  2254. lenp = stream_get_endp (circuit->snd_stream);
  2255. stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
  2256. /* no need to send the source here, it is always us if we csnp */
  2257. stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
  2258. /* with zero circuit id - ref 9.10, 9.11 */
  2259. stream_putc (circuit->snd_stream, 0x00);
  2260. stream_put (circuit->snd_stream, start, ISIS_SYS_ID_LEN + 2);
  2261. stream_put (circuit->snd_stream, stop, ISIS_SYS_ID_LEN + 2);
  2262. /*
  2263. * And TLVs
  2264. */
  2265. if (level == IS_LEVEL_1)
  2266. passwd = &circuit->area->area_passwd;
  2267. else
  2268. passwd = &circuit->area->domain_passwd;
  2269. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
  2270. {
  2271. switch (passwd->type)
  2272. {
  2273. /* Cleartext */
  2274. case ISIS_PASSWD_TYPE_CLEARTXT:
  2275. if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len,
  2276. passwd->passwd, circuit->snd_stream))
  2277. return ISIS_WARNING;
  2278. break;
  2279. /* HMAC MD5 */
  2280. case ISIS_PASSWD_TYPE_HMAC_MD5:
  2281. /* Remember where TLV is written so we can later overwrite the MD5 hash */
  2282. auth_tlv_offset = stream_get_endp (circuit->snd_stream);
  2283. memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
  2284. if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE,
  2285. hmac_md5_hash, circuit->snd_stream))
  2286. return ISIS_WARNING;
  2287. break;
  2288. default:
  2289. break;
  2290. }
  2291. }
  2292. retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
  2293. if (retval != ISIS_OK)
  2294. return retval;
  2295. length = (u_int16_t) stream_get_endp (circuit->snd_stream);
  2296. /* Update PU length */
  2297. stream_putw_at (circuit->snd_stream, lenp, length);
  2298. /* For HMAC MD5 we need to compute the md5 hash and store it */
  2299. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) &&
  2300. passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5)
  2301. {
  2302. hmac_md5 (STREAM_DATA (circuit->snd_stream),
  2303. stream_get_endp(circuit->snd_stream),
  2304. (unsigned char *) &passwd->passwd, passwd->len,
  2305. (unsigned char *) &hmac_md5_hash);
  2306. /* Copy the hash into the stream */
  2307. memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
  2308. hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
  2309. }
  2310. return retval;
  2311. }
  2312. /*
  2313. * Count the maximum number of lsps that can be accomodated by a given size.
  2314. */
  2315. static uint16_t
  2316. get_max_lsp_count (uint16_t size)
  2317. {
  2318. uint16_t tlv_count;
  2319. uint16_t lsp_count;
  2320. uint16_t remaining_size;
  2321. /* First count the full size TLVs */
  2322. tlv_count = size / MAX_LSP_ENTRIES_TLV_SIZE;
  2323. lsp_count = tlv_count * (MAX_LSP_ENTRIES_TLV_SIZE / LSP_ENTRIES_LEN);
  2324. /* The last TLV, if any */
  2325. remaining_size = size % MAX_LSP_ENTRIES_TLV_SIZE;
  2326. if (remaining_size - 2 >= LSP_ENTRIES_LEN)
  2327. lsp_count += (remaining_size - 2) / LSP_ENTRIES_LEN;
  2328. return lsp_count;
  2329. }
  2330. /*
  2331. * Calculate the length of Authentication Info. TLV.
  2332. */
  2333. static uint16_t
  2334. auth_tlv_length (int level, struct isis_circuit *circuit)
  2335. {
  2336. struct isis_passwd *passwd;
  2337. uint16_t length;
  2338. if (level == IS_LEVEL_1)
  2339. passwd = &circuit->area->area_passwd;
  2340. else
  2341. passwd = &circuit->area->domain_passwd;
  2342. /* Also include the length of TLV header */
  2343. length = AUTH_INFO_HDRLEN;
  2344. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
  2345. {
  2346. switch (passwd->type)
  2347. {
  2348. /* Cleartext */
  2349. case ISIS_PASSWD_TYPE_CLEARTXT:
  2350. length += passwd->len;
  2351. break;
  2352. /* HMAC MD5 */
  2353. case ISIS_PASSWD_TYPE_HMAC_MD5:
  2354. length += ISIS_AUTH_MD5_SIZE;
  2355. break;
  2356. default:
  2357. break;
  2358. }
  2359. }
  2360. return length;
  2361. }
  2362. /*
  2363. * Calculate the maximum number of lsps that can be accomodated in a CSNP/PSNP.
  2364. */
  2365. static uint16_t
  2366. max_lsps_per_snp (int snp_type, int level, struct isis_circuit *circuit)
  2367. {
  2368. int snp_hdr_len;
  2369. int auth_tlv_len;
  2370. uint16_t lsp_count;
  2371. snp_hdr_len = ISIS_FIXED_HDR_LEN;
  2372. if (snp_type == ISIS_SNP_CSNP_FLAG)
  2373. snp_hdr_len += ISIS_CSNP_HDRLEN;
  2374. else
  2375. snp_hdr_len += ISIS_PSNP_HDRLEN;
  2376. auth_tlv_len = auth_tlv_length (level, circuit);
  2377. lsp_count = get_max_lsp_count (
  2378. stream_get_size (circuit->snd_stream) - snp_hdr_len - auth_tlv_len);
  2379. return lsp_count;
  2380. }
  2381. /*
  2382. * FIXME: support multiple CSNPs
  2383. */
  2384. int
  2385. send_csnp (struct isis_circuit *circuit, int level)
  2386. {
  2387. u_char start[ISIS_SYS_ID_LEN + 2];
  2388. u_char stop[ISIS_SYS_ID_LEN + 2];
  2389. struct list *list = NULL;
  2390. struct listnode *node;
  2391. struct isis_lsp *lsp;
  2392. u_char num_lsps, loop = 1;
  2393. int i, retval = ISIS_OK;
  2394. if (circuit->area->lspdb[level - 1] == NULL ||
  2395. dict_count (circuit->area->lspdb[level - 1]) == 0)
  2396. return retval;
  2397. memset (start, 0x00, ISIS_SYS_ID_LEN + 2);
  2398. memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
  2399. num_lsps = max_lsps_per_snp (ISIS_SNP_CSNP_FLAG, level, circuit);
  2400. while (loop)
  2401. {
  2402. list = list_new ();
  2403. lsp_build_list (start, stop, num_lsps, list,
  2404. circuit->area->lspdb[level - 1]);
  2405. /*
  2406. * Update the stop lsp_id before encoding this CSNP.
  2407. */
  2408. if (listcount (list) < num_lsps)
  2409. {
  2410. memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
  2411. }
  2412. else
  2413. {
  2414. node = listtail (list);
  2415. lsp = listgetdata (node);
  2416. memcpy (stop, lsp->lsp_header->lsp_id, ISIS_SYS_ID_LEN + 2);
  2417. }
  2418. retval = build_csnp (level, start, stop, list, circuit);
  2419. if (retval != ISIS_OK)
  2420. {
  2421. zlog_err ("ISIS-Snp (%s): Build L%d CSNP on %s failed",
  2422. circuit->area->area_tag, level, circuit->interface->name);
  2423. list_delete (list);
  2424. return retval;
  2425. }
  2426. if (isis->debugs & DEBUG_SNP_PACKETS)
  2427. {
  2428. zlog_debug ("ISIS-Snp (%s): Sent L%d CSNP on %s, length %zd",
  2429. circuit->area->area_tag, level, circuit->interface->name,
  2430. stream_get_endp (circuit->snd_stream));
  2431. for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
  2432. {
  2433. zlog_debug ("ISIS-Snp (%s): CSNP entry %s, seq 0x%08x,"
  2434. " cksum 0x%04x, lifetime %us",
  2435. circuit->area->area_tag,
  2436. rawlspid_print (lsp->lsp_header->lsp_id),
  2437. ntohl (lsp->lsp_header->seq_num),
  2438. ntohs (lsp->lsp_header->checksum),
  2439. ntohs (lsp->lsp_header->rem_lifetime));
  2440. }
  2441. if (isis->debugs & DEBUG_PACKET_DUMP)
  2442. zlog_dump_data (STREAM_DATA (circuit->snd_stream),
  2443. stream_get_endp (circuit->snd_stream));
  2444. }
  2445. retval = circuit->tx (circuit, level);
  2446. if (retval != ISIS_OK)
  2447. {
  2448. zlog_err ("ISIS-Snp (%s): Send L%d CSNP on %s failed",
  2449. circuit->area->area_tag, level,
  2450. circuit->interface->name);
  2451. list_delete (list);
  2452. return retval;
  2453. }
  2454. /*
  2455. * Start lsp_id of the next CSNP should be one plus the
  2456. * stop lsp_id in this current CSNP.
  2457. */
  2458. memcpy (start, stop, ISIS_SYS_ID_LEN + 2);
  2459. loop = 0;
  2460. for (i = ISIS_SYS_ID_LEN + 1; i >= 0; --i)
  2461. {
  2462. if (start[i] < (u_char)0xff)
  2463. {
  2464. start[i] += 1;
  2465. loop = 1;
  2466. break;
  2467. }
  2468. }
  2469. memset (stop, 0xff, ISIS_SYS_ID_LEN + 2);
  2470. list_delete (list);
  2471. }
  2472. return retval;
  2473. }
  2474. int
  2475. send_l1_csnp (struct thread *thread)
  2476. {
  2477. struct isis_circuit *circuit;
  2478. int retval = ISIS_OK;
  2479. circuit = THREAD_ARG (thread);
  2480. assert (circuit);
  2481. circuit->t_send_csnp[0] = NULL;
  2482. if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[0])
  2483. {
  2484. send_csnp (circuit, 1);
  2485. }
  2486. /* set next timer thread */
  2487. THREAD_TIMER_ON (master, circuit->t_send_csnp[0], send_l1_csnp, circuit,
  2488. isis_jitter (circuit->csnp_interval[0], CSNP_JITTER));
  2489. return retval;
  2490. }
  2491. int
  2492. send_l2_csnp (struct thread *thread)
  2493. {
  2494. struct isis_circuit *circuit;
  2495. int retval = ISIS_OK;
  2496. circuit = THREAD_ARG (thread);
  2497. assert (circuit);
  2498. circuit->t_send_csnp[1] = NULL;
  2499. if (circuit->circ_type == CIRCUIT_T_BROADCAST && circuit->u.bc.is_dr[1])
  2500. {
  2501. send_csnp (circuit, 2);
  2502. }
  2503. /* set next timer thread */
  2504. THREAD_TIMER_ON (master, circuit->t_send_csnp[1], send_l2_csnp, circuit,
  2505. isis_jitter (circuit->csnp_interval[1], CSNP_JITTER));
  2506. return retval;
  2507. }
  2508. static int
  2509. build_psnp (int level, struct isis_circuit *circuit, struct list *lsps)
  2510. {
  2511. struct isis_fixed_hdr fixed_hdr;
  2512. unsigned long lenp;
  2513. u_int16_t length;
  2514. struct isis_lsp *lsp;
  2515. struct isis_passwd *passwd;
  2516. struct listnode *node;
  2517. unsigned char hmac_md5_hash[ISIS_AUTH_MD5_SIZE];
  2518. unsigned long auth_tlv_offset = 0;
  2519. int retval = ISIS_OK;
  2520. isis_circuit_stream(circuit, &circuit->snd_stream);
  2521. if (level == IS_LEVEL_1)
  2522. fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
  2523. circuit->snd_stream);
  2524. else
  2525. fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
  2526. circuit->snd_stream);
  2527. /*
  2528. * Fill Level 1 or 2 Partial Sequence Numbers header
  2529. */
  2530. lenp = stream_get_endp (circuit->snd_stream);
  2531. stream_putw (circuit->snd_stream, 0); /* PDU length - when we know it */
  2532. stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
  2533. stream_putc (circuit->snd_stream, circuit->idx);
  2534. /*
  2535. * And TLVs
  2536. */
  2537. if (level == IS_LEVEL_1)
  2538. passwd = &circuit->area->area_passwd;
  2539. else
  2540. passwd = &circuit->area->domain_passwd;
  2541. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND))
  2542. {
  2543. switch (passwd->type)
  2544. {
  2545. /* Cleartext */
  2546. case ISIS_PASSWD_TYPE_CLEARTXT:
  2547. if (tlv_add_authinfo (ISIS_PASSWD_TYPE_CLEARTXT, passwd->len,
  2548. passwd->passwd, circuit->snd_stream))
  2549. return ISIS_WARNING;
  2550. break;
  2551. /* HMAC MD5 */
  2552. case ISIS_PASSWD_TYPE_HMAC_MD5:
  2553. /* Remember where TLV is written so we can later overwrite the MD5 hash */
  2554. auth_tlv_offset = stream_get_endp (circuit->snd_stream);
  2555. memset(&hmac_md5_hash, 0, ISIS_AUTH_MD5_SIZE);
  2556. if (tlv_add_authinfo (ISIS_PASSWD_TYPE_HMAC_MD5, ISIS_AUTH_MD5_SIZE,
  2557. hmac_md5_hash, circuit->snd_stream))
  2558. return ISIS_WARNING;
  2559. break;
  2560. default:
  2561. break;
  2562. }
  2563. }
  2564. retval = tlv_add_lsp_entries (lsps, circuit->snd_stream);
  2565. if (retval != ISIS_OK)
  2566. return retval;
  2567. if (isis->debugs & DEBUG_SNP_PACKETS)
  2568. {
  2569. for (ALL_LIST_ELEMENTS_RO (lsps, node, lsp))
  2570. {
  2571. zlog_debug ("ISIS-Snp (%s): PSNP entry %s, seq 0x%08x,"
  2572. " cksum 0x%04x, lifetime %us",
  2573. circuit->area->area_tag,
  2574. rawlspid_print (lsp->lsp_header->lsp_id),
  2575. ntohl (lsp->lsp_header->seq_num),
  2576. ntohs (lsp->lsp_header->checksum),
  2577. ntohs (lsp->lsp_header->rem_lifetime));
  2578. }
  2579. }
  2580. length = (u_int16_t) stream_get_endp (circuit->snd_stream);
  2581. /* Update PDU length */
  2582. stream_putw_at (circuit->snd_stream, lenp, length);
  2583. /* For HMAC MD5 we need to compute the md5 hash and store it */
  2584. if (CHECK_FLAG(passwd->snp_auth, SNP_AUTH_SEND) &&
  2585. passwd->type == ISIS_PASSWD_TYPE_HMAC_MD5)
  2586. {
  2587. hmac_md5 (STREAM_DATA (circuit->snd_stream),
  2588. stream_get_endp(circuit->snd_stream),
  2589. (unsigned char *) &passwd->passwd, passwd->len,
  2590. (unsigned char *) &hmac_md5_hash);
  2591. /* Copy the hash into the stream */
  2592. memcpy (STREAM_DATA (circuit->snd_stream) + auth_tlv_offset + 3,
  2593. hmac_md5_hash, ISIS_AUTH_MD5_SIZE);
  2594. }
  2595. return ISIS_OK;
  2596. }
  2597. /*
  2598. * 7.3.15.4 action on expiration of partial SNP interval
  2599. * level 1
  2600. */
  2601. static int
  2602. send_psnp (int level, struct isis_circuit *circuit)
  2603. {
  2604. struct isis_lsp *lsp;
  2605. struct list *list = NULL;
  2606. struct listnode *node;
  2607. u_char num_lsps;
  2608. int retval = ISIS_OK;
  2609. if (circuit->circ_type == CIRCUIT_T_BROADCAST &&
  2610. circuit->u.bc.is_dr[level - 1])
  2611. return ISIS_OK;
  2612. if (circuit->area->lspdb[level - 1] == NULL ||
  2613. dict_count (circuit->area->lspdb[level - 1]) == 0)
  2614. return ISIS_OK;
  2615. if (! circuit->snd_stream)
  2616. return ISIS_ERROR;
  2617. num_lsps = max_lsps_per_snp (ISIS_SNP_PSNP_FLAG, level, circuit);
  2618. while (1)
  2619. {
  2620. list = list_new ();
  2621. lsp_build_list_ssn (circuit, num_lsps, list,
  2622. circuit->area->lspdb[level - 1]);
  2623. if (listcount (list) == 0)
  2624. {
  2625. list_delete (list);
  2626. return ISIS_OK;
  2627. }
  2628. retval = build_psnp (level, circuit, list);
  2629. if (retval != ISIS_OK)
  2630. {
  2631. zlog_err ("ISIS-Snp (%s): Build L%d PSNP on %s failed",
  2632. circuit->area->area_tag, level, circuit->interface->name);
  2633. list_delete (list);
  2634. return retval;
  2635. }
  2636. if (isis->debugs & DEBUG_SNP_PACKETS)
  2637. {
  2638. zlog_debug ("ISIS-Snp (%s): Sent L%d PSNP on %s, length %zd",
  2639. circuit->area->area_tag, level,
  2640. circuit->interface->name,
  2641. stream_get_endp (circuit->snd_stream));
  2642. if (isis->debugs & DEBUG_PACKET_DUMP)
  2643. zlog_dump_data (STREAM_DATA (circuit->snd_stream),
  2644. stream_get_endp (circuit->snd_stream));
  2645. }
  2646. retval = circuit->tx (circuit, level);
  2647. if (retval != ISIS_OK)
  2648. {
  2649. zlog_err ("ISIS-Snp (%s): Send L%d PSNP on %s failed",
  2650. circuit->area->area_tag, level,
  2651. circuit->interface->name);
  2652. list_delete (list);
  2653. return retval;
  2654. }
  2655. /*
  2656. * sending succeeded, we can clear SSN flags of this circuit
  2657. * for the LSPs in list
  2658. */
  2659. for (ALL_LIST_ELEMENTS_RO (list, node, lsp))
  2660. ISIS_CLEAR_FLAG (lsp->SSNflags, circuit);
  2661. list_delete (list);
  2662. }
  2663. return retval;
  2664. }
  2665. int
  2666. send_l1_psnp (struct thread *thread)
  2667. {
  2668. struct isis_circuit *circuit;
  2669. int retval = ISIS_OK;
  2670. circuit = THREAD_ARG (thread);
  2671. assert (circuit);
  2672. circuit->t_send_psnp[0] = NULL;
  2673. send_psnp (1, circuit);
  2674. /* set next timer thread */
  2675. THREAD_TIMER_ON (master, circuit->t_send_psnp[0], send_l1_psnp, circuit,
  2676. isis_jitter (circuit->psnp_interval[0], PSNP_JITTER));
  2677. return retval;
  2678. }
  2679. /*
  2680. * 7.3.15.4 action on expiration of partial SNP interval
  2681. * level 2
  2682. */
  2683. int
  2684. send_l2_psnp (struct thread *thread)
  2685. {
  2686. struct isis_circuit *circuit;
  2687. int retval = ISIS_OK;
  2688. circuit = THREAD_ARG (thread);
  2689. assert (circuit);
  2690. circuit->t_send_psnp[1] = NULL;
  2691. send_psnp (2, circuit);
  2692. /* set next timer thread */
  2693. THREAD_TIMER_ON (master, circuit->t_send_psnp[1], send_l2_psnp, circuit,
  2694. isis_jitter (circuit->psnp_interval[1], PSNP_JITTER));
  2695. return retval;
  2696. }
  2697. /*
  2698. * ISO 10589 - 7.3.14.3
  2699. */
  2700. int
  2701. send_lsp (struct thread *thread)
  2702. {
  2703. struct isis_circuit *circuit;
  2704. struct isis_lsp *lsp;
  2705. struct listnode *node;
  2706. int retval = ISIS_OK;
  2707. circuit = THREAD_ARG (thread);
  2708. assert (circuit);
  2709. if (circuit->state != C_STATE_UP || circuit->is_passive == 1)
  2710. {
  2711. return retval;
  2712. }
  2713. node = listhead (circuit->lsp_queue);
  2714. /*
  2715. * Handle case where there are no LSPs on the queue. This can
  2716. * happen, for instance, if an adjacency goes down before this
  2717. * thread gets a chance to run.
  2718. */
  2719. if (!node)
  2720. {
  2721. return retval;
  2722. }
  2723. lsp = listgetdata(node);
  2724. /*
  2725. * Do not send if levels do not match
  2726. */
  2727. if (!(lsp->level & circuit->is_type))
  2728. {
  2729. list_delete_node (circuit->lsp_queue, node);
  2730. return retval;
  2731. }
  2732. /*
  2733. * Do not send if we do not have adjacencies in state up on the circuit
  2734. */
  2735. if (circuit->upadjcount[lsp->level - 1] == 0)
  2736. {
  2737. list_delete_node (circuit->lsp_queue, node);
  2738. return retval;
  2739. }
  2740. /* copy our lsp to the send buffer */
  2741. stream_copy (circuit->snd_stream, lsp->pdu);
  2742. if (isis->debugs & DEBUG_UPDATE_PACKETS)
  2743. {
  2744. zlog_debug
  2745. ("ISIS-Upd (%s): Sent L%d LSP %s, seq 0x%08x, cksum 0x%04x,"
  2746. " lifetime %us on %s", circuit->area->area_tag, lsp->level,
  2747. rawlspid_print (lsp->lsp_header->lsp_id),
  2748. ntohl (lsp->lsp_header->seq_num),
  2749. ntohs (lsp->lsp_header->checksum),
  2750. ntohs (lsp->lsp_header->rem_lifetime),
  2751. circuit->interface->name);
  2752. if (isis->debugs & DEBUG_PACKET_DUMP)
  2753. zlog_dump_data (STREAM_DATA (circuit->snd_stream),
  2754. stream_get_endp (circuit->snd_stream));
  2755. }
  2756. retval = circuit->tx (circuit, lsp->level);
  2757. if (retval != ISIS_OK)
  2758. {
  2759. zlog_err ("ISIS-Upd (%s): Send L%d LSP on %s failed",
  2760. circuit->area->area_tag, lsp->level,
  2761. circuit->interface->name);
  2762. return retval;
  2763. }
  2764. /*
  2765. * If the sending succeeded, we can del the lsp from circuits
  2766. * lsp_queue
  2767. */
  2768. list_delete_node (circuit->lsp_queue, node);
  2769. /* Set the last-cleared time if the queue is empty. */
  2770. /* TODO: Is is possible that new lsps keep being added to the queue
  2771. * that the queue is never empty? */
  2772. if (list_isempty (circuit->lsp_queue))
  2773. circuit->lsp_queue_last_cleared = time (NULL);
  2774. /*
  2775. * On broadcast circuits also the SRMflag can be cleared
  2776. */
  2777. if (circuit->circ_type == CIRCUIT_T_BROADCAST)
  2778. ISIS_CLEAR_FLAG (lsp->SRMflags, circuit);
  2779. return retval;
  2780. }
  2781. int
  2782. ack_lsp (struct isis_link_state_hdr *hdr, struct isis_circuit *circuit,
  2783. int level)
  2784. {
  2785. unsigned long lenp;
  2786. int retval;
  2787. u_int16_t length;
  2788. struct isis_fixed_hdr fixed_hdr;
  2789. isis_circuit_stream(circuit, &circuit->snd_stream);
  2790. // fill_llc_hdr (stream);
  2791. if (level == IS_LEVEL_1)
  2792. fill_fixed_hdr_andstream (&fixed_hdr, L1_PARTIAL_SEQ_NUM,
  2793. circuit->snd_stream);
  2794. else
  2795. fill_fixed_hdr_andstream (&fixed_hdr, L2_PARTIAL_SEQ_NUM,
  2796. circuit->snd_stream);
  2797. lenp = stream_get_endp (circuit->snd_stream);
  2798. stream_putw (circuit->snd_stream, 0); /* PDU length */
  2799. stream_put (circuit->snd_stream, isis->sysid, ISIS_SYS_ID_LEN);
  2800. stream_putc (circuit->snd_stream, circuit->idx);
  2801. stream_putc (circuit->snd_stream, 9); /* code */
  2802. stream_putc (circuit->snd_stream, 16); /* len */
  2803. stream_putw (circuit->snd_stream, ntohs (hdr->rem_lifetime));
  2804. stream_put (circuit->snd_stream, hdr->lsp_id, ISIS_SYS_ID_LEN + 2);
  2805. stream_putl (circuit->snd_stream, ntohl (hdr->seq_num));
  2806. stream_putw (circuit->snd_stream, ntohs (hdr->checksum));
  2807. length = (u_int16_t) stream_get_endp (circuit->snd_stream);
  2808. /* Update PDU length */
  2809. stream_putw_at (circuit->snd_stream, lenp, length);
  2810. retval = circuit->tx (circuit, level);
  2811. if (retval != ISIS_OK)
  2812. zlog_err ("ISIS-Upd (%s): Send L%d LSP PSNP on %s failed",
  2813. circuit->area->area_tag, level,
  2814. circuit->interface->name);
  2815. return retval;
  2816. }