isis_pdu.c 91 KB

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