bgp_open.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145
  1. /* BGP open message handling
  2. Copyright (C) 1998, 1999 Kunihiro Ishiguro
  3. This file is part of GNU Zebra.
  4. GNU Zebra is free software; you can redistribute it and/or modify it
  5. under the terms of the GNU General Public License as published by the
  6. Free Software Foundation; either version 2, or (at your option) any
  7. later version.
  8. GNU Zebra is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNU Zebra; see the file COPYING. If not, write to the Free
  14. Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA. */
  16. #include <zebra.h>
  17. #include "linklist.h"
  18. #include "prefix.h"
  19. #include "stream.h"
  20. #include "thread.h"
  21. #include "log.h"
  22. #include "command.h"
  23. #include "memory.h"
  24. #include "filter.h"
  25. #include "bgpd/bgpd.h"
  26. #include "bgpd/bgp_attr.h"
  27. #include "bgpd/bgp_debug.h"
  28. #include "bgpd/bgp_fsm.h"
  29. #include "bgpd/bgp_packet.h"
  30. #include "bgpd/bgp_open.h"
  31. #include "bgpd/bgp_aspath.h"
  32. #include "bgpd/bgp_vty.h"
  33. /* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
  34. negotiate remote peer supports extentions or not. But if
  35. remote-peer doesn't supports negotiation process itself. We would
  36. like to do manual configuration.
  37. So there is many configurable point. First of all we want set each
  38. peer whether we send capability negotiation to the peer or not.
  39. Next, if we send capability to the peer we want to set my capabilty
  40. inforation at each peer. */
  41. void
  42. bgp_capability_vty_out (struct vty *vty, struct peer *peer)
  43. {
  44. char *pnt;
  45. char *end;
  46. struct capability_mp_data mpc;
  47. struct capability_header *hdr;
  48. pnt = peer->notify.data;
  49. end = pnt + peer->notify.length;
  50. while (pnt < end)
  51. {
  52. if (pnt + sizeof (struct capability_mp_data) + 2 > end)
  53. return;
  54. hdr = (struct capability_header *)pnt;
  55. if (pnt + hdr->length + 2 > end)
  56. return;
  57. memcpy (&mpc, pnt + 2, sizeof(struct capability_mp_data));
  58. if (hdr->code == CAPABILITY_CODE_MP)
  59. {
  60. vty_out (vty, " Capability error for: Multi protocol ");
  61. switch (ntohs (mpc.afi))
  62. {
  63. case AFI_IP:
  64. vty_out (vty, "AFI IPv4, ");
  65. break;
  66. case AFI_IP6:
  67. vty_out (vty, "AFI IPv6, ");
  68. break;
  69. default:
  70. vty_out (vty, "AFI Unknown %d, ", ntohs (mpc.afi));
  71. break;
  72. }
  73. switch (mpc.safi)
  74. {
  75. case SAFI_UNICAST:
  76. vty_out (vty, "SAFI Unicast");
  77. break;
  78. case SAFI_MULTICAST:
  79. vty_out (vty, "SAFI Multicast");
  80. break;
  81. case SAFI_MPLS_LABELED_VPN:
  82. vty_out (vty, "SAFI MPLS-labeled VPN");
  83. break;
  84. case SAFI_ENCAP:
  85. vty_out (vty, "SAFI ENCAP");
  86. break;
  87. default:
  88. vty_out (vty, "SAFI Unknown %d ", mpc.safi);
  89. break;
  90. }
  91. vty_out (vty, "%s", VTY_NEWLINE);
  92. }
  93. else if (hdr->code >= 128)
  94. vty_out (vty, " Capability error: vendor specific capability code %d",
  95. hdr->code);
  96. else
  97. vty_out (vty, " Capability error: unknown capability code %d",
  98. hdr->code);
  99. pnt += hdr->length + 2;
  100. }
  101. }
  102. static void
  103. bgp_capability_mp_data (struct stream *s, struct capability_mp_data *mpc)
  104. {
  105. afi_t afi = stream_getw (s);
  106. memcpy(&mpc->afi, &afi, sizeof(mpc->afi));
  107. mpc->reserved = stream_getc (s);
  108. mpc->safi = stream_getc (s);
  109. }
  110. int
  111. bgp_afi_safi_valid_indices (afi_t afi, safi_t *safi)
  112. {
  113. switch (afi)
  114. {
  115. case AFI_IP:
  116. case AFI_IP6:
  117. switch (*safi)
  118. {
  119. /* BGP MPLS-labeled VPN SAFI isn't contigious with others, remap */
  120. case SAFI_MPLS_LABELED_VPN:
  121. *safi = SAFI_MPLS_VPN;
  122. case SAFI_UNICAST:
  123. case SAFI_MULTICAST:
  124. case SAFI_MPLS_VPN:
  125. case SAFI_ENCAP:
  126. return 1;
  127. }
  128. case AFI_ETHER:
  129. default:
  130. break;
  131. }
  132. zlog_debug ("unknown afi/safi (%u/%u)", afi, *safi);
  133. return 0;
  134. }
  135. /* Set negotiated capability value. */
  136. static int
  137. bgp_capability_mp (struct peer *peer, struct capability_header *hdr)
  138. {
  139. struct capability_mp_data mpc;
  140. struct stream *s = BGP_INPUT (peer);
  141. bgp_capability_mp_data (s, &mpc);
  142. if (BGP_DEBUG (normal, NORMAL))
  143. zlog_debug ("%s OPEN has MP_EXT CAP for afi/safi: %u/%u",
  144. peer->host, mpc.afi, mpc.safi);
  145. if (!bgp_afi_safi_valid_indices (mpc.afi, &mpc.safi))
  146. return -1;
  147. /* Now safi remapped, and afi/safi are valid array indices */
  148. peer->afc_recv[mpc.afi][mpc.safi] = 1;
  149. if (peer->afc[mpc.afi][mpc.safi])
  150. peer->afc_nego[mpc.afi][mpc.safi] = 1;
  151. else
  152. return -1;
  153. return 0;
  154. }
  155. static void
  156. bgp_capability_orf_not_support (struct peer *peer, afi_t afi, safi_t safi,
  157. u_char type, u_char mode)
  158. {
  159. if (BGP_DEBUG (normal, NORMAL))
  160. zlog_debug ("%s Addr-family %d/%d has ORF type/mode %d/%d not supported",
  161. peer->host, afi, safi, type, mode);
  162. }
  163. static const struct message orf_type_str[] =
  164. {
  165. { ORF_TYPE_PREFIX, "Prefixlist" },
  166. { ORF_TYPE_PREFIX_OLD, "Prefixlist (old)" },
  167. };
  168. static const int orf_type_str_max = array_size(orf_type_str);
  169. static const struct message orf_mode_str[] =
  170. {
  171. { ORF_MODE_RECEIVE, "Receive" },
  172. { ORF_MODE_SEND, "Send" },
  173. { ORF_MODE_BOTH, "Both" },
  174. };
  175. static const int orf_mode_str_max = array_size(orf_mode_str);
  176. static int
  177. bgp_capability_orf_entry (struct peer *peer, struct capability_header *hdr)
  178. {
  179. struct stream *s = BGP_INPUT (peer);
  180. struct capability_orf_entry entry;
  181. afi_t afi;
  182. safi_t safi;
  183. u_char type;
  184. u_char mode;
  185. u_int16_t sm_cap = 0; /* capability send-mode receive */
  186. u_int16_t rm_cap = 0; /* capability receive-mode receive */
  187. int i;
  188. /* ORF Entry header */
  189. bgp_capability_mp_data (s, &entry.mpc);
  190. entry.num = stream_getc (s);
  191. afi = entry.mpc.afi;
  192. safi = entry.mpc.safi;
  193. if (BGP_DEBUG (normal, NORMAL))
  194. zlog_debug ("%s ORF Cap entry for afi/safi: %u/%u",
  195. peer->host, entry.mpc.afi, entry.mpc.safi);
  196. /* Check AFI and SAFI. */
  197. if (!bgp_afi_safi_valid_indices (entry.mpc.afi, &safi))
  198. {
  199. zlog_info ("%s Addr-family %d/%d not supported."
  200. " Ignoring the ORF capability",
  201. peer->host, entry.mpc.afi, entry.mpc.safi);
  202. return 0;
  203. }
  204. /* validate number field */
  205. if (CAPABILITY_CODE_ORF_LEN + (entry.num * 2) > hdr->length)
  206. {
  207. zlog_info ("%s ORF Capability entry length error,"
  208. " Cap length %u, num %u",
  209. peer->host, hdr->length, entry.num);
  210. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  211. return -1;
  212. }
  213. for (i = 0 ; i < entry.num ; i++)
  214. {
  215. type = stream_getc(s);
  216. mode = stream_getc(s);
  217. /* ORF Mode error check */
  218. switch (mode)
  219. {
  220. case ORF_MODE_BOTH:
  221. case ORF_MODE_SEND:
  222. case ORF_MODE_RECEIVE:
  223. break;
  224. default:
  225. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  226. continue;
  227. }
  228. /* ORF Type and afi/safi error checks */
  229. /* capcode versus type */
  230. switch (hdr->code)
  231. {
  232. case CAPABILITY_CODE_ORF:
  233. switch (type)
  234. {
  235. case ORF_TYPE_PREFIX:
  236. break;
  237. default:
  238. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  239. continue;
  240. }
  241. break;
  242. case CAPABILITY_CODE_ORF_OLD:
  243. switch (type)
  244. {
  245. case ORF_TYPE_PREFIX_OLD:
  246. break;
  247. default:
  248. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  249. continue;
  250. }
  251. break;
  252. default:
  253. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  254. continue;
  255. }
  256. /* AFI vs SAFI */
  257. if (!((afi == AFI_IP && safi == SAFI_UNICAST)
  258. || (afi == AFI_IP && safi == SAFI_MULTICAST)
  259. || (afi == AFI_IP6 && safi == SAFI_UNICAST)))
  260. {
  261. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  262. continue;
  263. }
  264. if (BGP_DEBUG (normal, NORMAL))
  265. zlog_debug ("%s OPEN has %s ORF capability"
  266. " as %s for afi/safi: %d/%d",
  267. peer->host, LOOKUP (orf_type_str, type),
  268. LOOKUP (orf_mode_str, mode),
  269. entry.mpc.afi, safi);
  270. if (hdr->code == CAPABILITY_CODE_ORF)
  271. {
  272. sm_cap = PEER_CAP_ORF_PREFIX_SM_RCV;
  273. rm_cap = PEER_CAP_ORF_PREFIX_RM_RCV;
  274. }
  275. else if (hdr->code == CAPABILITY_CODE_ORF_OLD)
  276. {
  277. sm_cap = PEER_CAP_ORF_PREFIX_SM_OLD_RCV;
  278. rm_cap = PEER_CAP_ORF_PREFIX_RM_OLD_RCV;
  279. }
  280. else
  281. {
  282. bgp_capability_orf_not_support (peer, afi, safi, type, mode);
  283. continue;
  284. }
  285. switch (mode)
  286. {
  287. case ORF_MODE_BOTH:
  288. SET_FLAG (peer->af_cap[afi][safi], sm_cap);
  289. SET_FLAG (peer->af_cap[afi][safi], rm_cap);
  290. break;
  291. case ORF_MODE_SEND:
  292. SET_FLAG (peer->af_cap[afi][safi], sm_cap);
  293. break;
  294. case ORF_MODE_RECEIVE:
  295. SET_FLAG (peer->af_cap[afi][safi], rm_cap);
  296. break;
  297. }
  298. }
  299. return 0;
  300. }
  301. static int
  302. bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
  303. {
  304. struct stream *s = BGP_INPUT (peer);
  305. u_int16_t restart_flag_time;
  306. size_t end = stream_get_getp (s) + caphdr->length;
  307. SET_FLAG (peer->cap, PEER_CAP_RESTART_RCV);
  308. restart_flag_time = stream_getw(s);
  309. if (CHECK_FLAG (restart_flag_time, RESTART_R_BIT))
  310. SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV);
  311. UNSET_FLAG (restart_flag_time, 0xF000);
  312. peer->v_gr_restart = restart_flag_time;
  313. if (BGP_DEBUG (normal, NORMAL))
  314. {
  315. zlog_debug ("%s OPEN has Graceful Restart capability", peer->host);
  316. zlog_debug ("%s Peer has%srestarted. Restart Time : %d",
  317. peer->host,
  318. CHECK_FLAG (peer->cap, PEER_CAP_RESTART_BIT_RCV) ? " "
  319. : " not ",
  320. peer->v_gr_restart);
  321. }
  322. while (stream_get_getp (s) + 4 <= end)
  323. {
  324. afi_t afi = stream_getw (s);
  325. safi_t safi = stream_getc (s);
  326. u_char flag = stream_getc (s);
  327. if (!bgp_afi_safi_valid_indices (afi, &safi))
  328. {
  329. if (BGP_DEBUG (normal, NORMAL))
  330. zlog_debug ("%s Addr-family %d/%d(afi/safi) not supported."
  331. " Ignore the Graceful Restart capability",
  332. peer->host, afi, safi);
  333. }
  334. else if (!peer->afc[afi][safi])
  335. {
  336. if (BGP_DEBUG (normal, NORMAL))
  337. zlog_debug ("%s Addr-family %d/%d(afi/safi) not enabled."
  338. " Ignore the Graceful Restart capability",
  339. peer->host, afi, safi);
  340. }
  341. else
  342. {
  343. if (BGP_DEBUG (normal, NORMAL))
  344. zlog_debug ("%s Address family %s is%spreserved", peer->host,
  345. afi_safi_print (afi, safi),
  346. CHECK_FLAG (peer->af_cap[afi][safi],
  347. PEER_CAP_RESTART_AF_PRESERVE_RCV)
  348. ? " " : " not ");
  349. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_RCV);
  350. if (CHECK_FLAG (flag, RESTART_F_BIT))
  351. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_RESTART_AF_PRESERVE_RCV);
  352. }
  353. }
  354. return 0;
  355. }
  356. static as_t
  357. bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
  358. {
  359. SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
  360. if (hdr->length != CAPABILITY_CODE_AS4_LEN)
  361. {
  362. zlog_err ("%s AS4 capability has incorrect data length %d",
  363. peer->host, hdr->length);
  364. return 0;
  365. }
  366. as_t as4 = stream_getl (BGP_INPUT(peer));
  367. if (BGP_DEBUG (as4, AS4))
  368. zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
  369. peer->host, as4);
  370. return as4;
  371. }
  372. static const struct message capcode_str[] =
  373. {
  374. { CAPABILITY_CODE_MP, "MultiProtocol Extensions" },
  375. { CAPABILITY_CODE_REFRESH, "Route Refresh" },
  376. { CAPABILITY_CODE_ORF, "Cooperative Route Filtering" },
  377. { CAPABILITY_CODE_RESTART, "Graceful Restart" },
  378. { CAPABILITY_CODE_AS4, "4-octet AS number" },
  379. { CAPABILITY_CODE_DYNAMIC, "Dynamic" },
  380. { CAPABILITY_CODE_REFRESH_OLD, "Route Refresh (Old)" },
  381. { CAPABILITY_CODE_ORF_OLD, "ORF (Old)" },
  382. };
  383. static const int capcode_str_max = array_size(capcode_str);
  384. /* Minimum sizes for length field of each cap (so not inc. the header) */
  385. static const size_t cap_minsizes[] =
  386. {
  387. [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
  388. [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
  389. [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
  390. [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
  391. [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
  392. [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
  393. [CAPABILITY_CODE_REFRESH_OLD] = CAPABILITY_CODE_REFRESH_LEN,
  394. [CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
  395. };
  396. /* value the capability must be a multiple of.
  397. * 0-data capabilities won't be checked against this.
  398. * Other capabilities whose data doesn't fall on convenient boundaries for this
  399. * table should be set to 1.
  400. */
  401. static const size_t cap_modsizes[] =
  402. {
  403. [CAPABILITY_CODE_MP] = 4,
  404. [CAPABILITY_CODE_REFRESH] = 1,
  405. [CAPABILITY_CODE_ORF] = 1,
  406. [CAPABILITY_CODE_RESTART] = 1,
  407. [CAPABILITY_CODE_AS4] = 4,
  408. [CAPABILITY_CODE_DYNAMIC] = 1,
  409. [CAPABILITY_CODE_REFRESH_OLD] = 1,
  410. [CAPABILITY_CODE_ORF_OLD] = 1,
  411. };
  412. /**
  413. * Parse given capability.
  414. * XXX: This is reading into a stream, but not using stream API
  415. *
  416. * @param[out] mp_capability Set to 1 on return iff one or more Multiprotocol
  417. * capabilities were encountered.
  418. */
  419. static int
  420. bgp_capability_parse (struct peer *peer, size_t length, int *mp_capability,
  421. u_char **error)
  422. {
  423. int ret;
  424. struct stream *s = BGP_INPUT (peer);
  425. size_t end = stream_get_getp (s) + length;
  426. assert (STREAM_READABLE (s) >= length);
  427. while (stream_get_getp (s) < end)
  428. {
  429. size_t start;
  430. u_char *sp = stream_pnt (s);
  431. struct capability_header caphdr;
  432. /* We need at least capability code and capability length. */
  433. if (stream_get_getp(s) + 2 > end)
  434. {
  435. zlog_info ("%s Capability length error (< header)", peer->host);
  436. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  437. return -1;
  438. }
  439. caphdr.code = stream_getc (s);
  440. caphdr.length = stream_getc (s);
  441. start = stream_get_getp (s);
  442. /* Capability length check sanity check. */
  443. if (start + caphdr.length > end)
  444. {
  445. zlog_info ("%s Capability length error (< length)", peer->host);
  446. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR, BGP_NOTIFY_OPEN_UNSPECIFIC);
  447. return -1;
  448. }
  449. if (BGP_DEBUG (normal, NORMAL))
  450. zlog_debug ("%s OPEN has %s capability (%u), length %u",
  451. peer->host,
  452. LOOKUP (capcode_str, caphdr.code),
  453. caphdr.code, caphdr.length);
  454. /* Length sanity check, type-specific, for known capabilities */
  455. switch (caphdr.code)
  456. {
  457. case CAPABILITY_CODE_MP:
  458. case CAPABILITY_CODE_REFRESH:
  459. case CAPABILITY_CODE_REFRESH_OLD:
  460. case CAPABILITY_CODE_ORF:
  461. case CAPABILITY_CODE_ORF_OLD:
  462. case CAPABILITY_CODE_RESTART:
  463. case CAPABILITY_CODE_AS4:
  464. case CAPABILITY_CODE_DYNAMIC:
  465. /* Check length. */
  466. if (caphdr.length < cap_minsizes[caphdr.code])
  467. {
  468. zlog_info ("%s %s Capability length error: got %u,"
  469. " expected at least %u",
  470. peer->host,
  471. LOOKUP (capcode_str, caphdr.code),
  472. caphdr.length,
  473. (unsigned) cap_minsizes[caphdr.code]);
  474. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  475. BGP_NOTIFY_OPEN_UNSPECIFIC);
  476. return -1;
  477. }
  478. if (caphdr.length
  479. && caphdr.length % cap_modsizes[caphdr.code] != 0)
  480. {
  481. zlog_info ("%s %s Capability length error: got %u,"
  482. " expected a multiple of %u",
  483. peer->host,
  484. LOOKUP (capcode_str, caphdr.code),
  485. caphdr.length,
  486. (unsigned) cap_modsizes[caphdr.code]);
  487. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  488. BGP_NOTIFY_OPEN_UNSPECIFIC);
  489. return -1;
  490. }
  491. /* we deliberately ignore unknown codes, see below */
  492. default:
  493. break;
  494. }
  495. switch (caphdr.code)
  496. {
  497. case CAPABILITY_CODE_MP:
  498. {
  499. *mp_capability = 1;
  500. /* Ignore capability when override-capability is set. */
  501. if (! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
  502. {
  503. /* Set negotiated value. */
  504. ret = bgp_capability_mp (peer, &caphdr);
  505. /* Unsupported Capability. */
  506. if (ret < 0)
  507. {
  508. /* Store return data. */
  509. memcpy (*error, sp, caphdr.length + 2);
  510. *error += caphdr.length + 2;
  511. }
  512. }
  513. }
  514. break;
  515. case CAPABILITY_CODE_REFRESH:
  516. case CAPABILITY_CODE_REFRESH_OLD:
  517. {
  518. /* BGP refresh capability */
  519. if (caphdr.code == CAPABILITY_CODE_REFRESH_OLD)
  520. SET_FLAG (peer->cap, PEER_CAP_REFRESH_OLD_RCV);
  521. else
  522. SET_FLAG (peer->cap, PEER_CAP_REFRESH_NEW_RCV);
  523. }
  524. break;
  525. case CAPABILITY_CODE_ORF:
  526. case CAPABILITY_CODE_ORF_OLD:
  527. if (bgp_capability_orf_entry (peer, &caphdr))
  528. return -1;
  529. break;
  530. case CAPABILITY_CODE_RESTART:
  531. if (bgp_capability_restart (peer, &caphdr))
  532. return -1;
  533. break;
  534. case CAPABILITY_CODE_DYNAMIC:
  535. SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_RCV);
  536. break;
  537. case CAPABILITY_CODE_AS4:
  538. /* Already handled as a special-case parsing of the capabilities
  539. * at the beginning of OPEN processing. So we care not a jot
  540. * for the value really, only error case.
  541. */
  542. if (!bgp_capability_as4 (peer, &caphdr))
  543. return -1;
  544. break;
  545. default:
  546. if (caphdr.code > 128)
  547. {
  548. /* We don't send Notification for unknown vendor specific
  549. capabilities. It seems reasonable for now... */
  550. zlog_warn ("%s Vendor specific capability %d",
  551. peer->host, caphdr.code);
  552. }
  553. else
  554. {
  555. zlog_warn ("%s unrecognized capability code: %d - ignored",
  556. peer->host, caphdr.code);
  557. memcpy (*error, sp, caphdr.length + 2);
  558. *error += caphdr.length + 2;
  559. }
  560. }
  561. if (stream_get_getp(s) != (start + caphdr.length))
  562. {
  563. if (stream_get_getp(s) > (start + caphdr.length))
  564. zlog_warn ("%s Cap-parser for %s read past cap-length, %u!",
  565. peer->host, LOOKUP (capcode_str, caphdr.code),
  566. caphdr.length);
  567. stream_set_getp (s, start + caphdr.length);
  568. }
  569. }
  570. return 0;
  571. }
  572. static int
  573. bgp_auth_parse (struct peer *peer, size_t length)
  574. {
  575. bgp_notify_send (peer,
  576. BGP_NOTIFY_OPEN_ERR,
  577. BGP_NOTIFY_OPEN_AUTH_FAILURE);
  578. return -1;
  579. }
  580. static int
  581. strict_capability_same (struct peer *peer)
  582. {
  583. int i, j;
  584. for (i = AFI_IP; i < AFI_MAX; i++)
  585. for (j = SAFI_UNICAST; j < SAFI_MAX; j++)
  586. if (peer->afc[i][j] != peer->afc_nego[i][j])
  587. return 0;
  588. return 1;
  589. }
  590. /* peek into option, stores ASN to *as4 if the AS4 capability was found.
  591. * Returns 0 if no as4 found, as4cap value otherwise.
  592. */
  593. as_t
  594. peek_for_as4_capability (struct peer *peer, u_char length)
  595. {
  596. struct stream *s = BGP_INPUT (peer);
  597. size_t orig_getp = stream_get_getp (s);
  598. size_t end = orig_getp + length;
  599. as_t as4 = 0;
  600. /* The full capability parser will better flag the error.. */
  601. if (STREAM_READABLE(s) < length)
  602. return 0;
  603. if (BGP_DEBUG (as4, AS4))
  604. zlog_info ("%s [AS4] rcv OPEN w/ OPTION parameter len: %u,"
  605. " peeking for as4",
  606. peer->host, length);
  607. /* the error cases we DONT handle, we ONLY try to read as4 out of
  608. * correctly formatted options.
  609. */
  610. while (stream_get_getp(s) < end)
  611. {
  612. u_char opt_type;
  613. u_char opt_length;
  614. /* Check the length. */
  615. if (stream_get_getp (s) + 2 > end)
  616. goto end;
  617. /* Fetch option type and length. */
  618. opt_type = stream_getc (s);
  619. opt_length = stream_getc (s);
  620. /* Option length check. */
  621. if (stream_get_getp (s) + opt_length > end)
  622. goto end;
  623. if (opt_type == BGP_OPEN_OPT_CAP)
  624. {
  625. unsigned long capd_start = stream_get_getp (s);
  626. unsigned long capd_end = capd_start + opt_length;
  627. assert (capd_end <= end);
  628. while (stream_get_getp (s) < capd_end)
  629. {
  630. struct capability_header hdr;
  631. if (stream_get_getp (s) + 2 > capd_end)
  632. goto end;
  633. hdr.code = stream_getc (s);
  634. hdr.length = stream_getc (s);
  635. if ((stream_get_getp(s) + hdr.length) > capd_end)
  636. goto end;
  637. if (hdr.code == CAPABILITY_CODE_AS4)
  638. {
  639. if (BGP_DEBUG (as4, AS4))
  640. zlog_info ("[AS4] found AS4 capability, about to parse");
  641. as4 = bgp_capability_as4 (peer, &hdr);
  642. goto end;
  643. }
  644. stream_forward_getp (s, hdr.length);
  645. }
  646. }
  647. }
  648. end:
  649. stream_set_getp (s, orig_getp);
  650. return as4;
  651. }
  652. /**
  653. * Parse open option.
  654. *
  655. * @param[out] mp_capability @see bgp_capability_parse() for semantics.
  656. */
  657. int
  658. bgp_open_option_parse (struct peer *peer, u_char length, int *mp_capability)
  659. {
  660. int ret;
  661. u_char *error;
  662. u_char error_data[BGP_MAX_PACKET_SIZE];
  663. struct stream *s = BGP_INPUT(peer);
  664. size_t end = stream_get_getp (s) + length;
  665. ret = 0;
  666. error = error_data;
  667. if (BGP_DEBUG (normal, NORMAL))
  668. zlog_debug ("%s rcv OPEN w/ OPTION parameter len: %u",
  669. peer->host, length);
  670. while (stream_get_getp(s) < end)
  671. {
  672. u_char opt_type;
  673. u_char opt_length;
  674. /* Must have at least an OPEN option header */
  675. if (STREAM_READABLE(s) < 2)
  676. {
  677. zlog_info ("%s Option length error", peer->host);
  678. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  679. BGP_NOTIFY_OPEN_UNSPECIFIC);
  680. return -1;
  681. }
  682. /* Fetch option type and length. */
  683. opt_type = stream_getc (s);
  684. opt_length = stream_getc (s);
  685. /* Option length check. */
  686. if (STREAM_READABLE (s) < opt_length)
  687. {
  688. zlog_info ("%s Option length error", peer->host);
  689. bgp_notify_send (peer, BGP_NOTIFY_OPEN_ERR,
  690. BGP_NOTIFY_OPEN_UNSPECIFIC);
  691. return -1;
  692. }
  693. if (BGP_DEBUG (normal, NORMAL))
  694. zlog_debug ("%s rcvd OPEN w/ optional parameter type %u (%s) len %u",
  695. peer->host, opt_type,
  696. opt_type == BGP_OPEN_OPT_AUTH ? "Authentication" :
  697. opt_type == BGP_OPEN_OPT_CAP ? "Capability" : "Unknown",
  698. opt_length);
  699. switch (opt_type)
  700. {
  701. case BGP_OPEN_OPT_AUTH:
  702. ret = bgp_auth_parse (peer, opt_length);
  703. break;
  704. case BGP_OPEN_OPT_CAP:
  705. ret = bgp_capability_parse (peer, opt_length, mp_capability, &error);
  706. break;
  707. default:
  708. bgp_notify_send (peer,
  709. BGP_NOTIFY_OPEN_ERR,
  710. BGP_NOTIFY_OPEN_UNSUP_PARAM);
  711. ret = -1;
  712. break;
  713. }
  714. /* Parse error. To accumulate all unsupported capability codes,
  715. bgp_capability_parse does not return -1 when encounter
  716. unsupported capability code. To detect that, please check
  717. error and erro_data pointer, like below. */
  718. if (ret < 0)
  719. return -1;
  720. }
  721. /* All OPEN option is parsed. Check capability when strict compare
  722. flag is enabled.*/
  723. if (CHECK_FLAG (peer->flags, PEER_FLAG_STRICT_CAP_MATCH))
  724. {
  725. /* If Unsupported Capability exists. */
  726. if (error != error_data)
  727. {
  728. bgp_notify_send_with_data (peer,
  729. BGP_NOTIFY_OPEN_ERR,
  730. BGP_NOTIFY_OPEN_UNSUP_CAPBL,
  731. error_data, error - error_data);
  732. return -1;
  733. }
  734. /* Check local capability does not negotiated with remote
  735. peer. */
  736. if (! strict_capability_same (peer))
  737. {
  738. bgp_notify_send (peer,
  739. BGP_NOTIFY_OPEN_ERR,
  740. BGP_NOTIFY_OPEN_UNSUP_CAPBL);
  741. return -1;
  742. }
  743. }
  744. /* Check there are no common AFI/SAFIs and send Unsupported Capability
  745. error. */
  746. if (*mp_capability &&
  747. ! CHECK_FLAG (peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
  748. {
  749. if (! peer->afc_nego[AFI_IP][SAFI_UNICAST]
  750. && ! peer->afc_nego[AFI_IP][SAFI_MULTICAST]
  751. && ! peer->afc_nego[AFI_IP][SAFI_MPLS_VPN]
  752. && ! peer->afc_nego[AFI_IP][SAFI_ENCAP]
  753. && ! peer->afc_nego[AFI_IP6][SAFI_UNICAST]
  754. && ! peer->afc_nego[AFI_IP6][SAFI_MULTICAST]
  755. && ! peer->afc_nego[AFI_IP6][SAFI_MPLS_VPN]
  756. && ! peer->afc_nego[AFI_IP6][SAFI_ENCAP])
  757. {
  758. plog_err (peer->log, "%s [Error] Configured AFI/SAFIs do not "
  759. "overlap with received MP capabilities",
  760. peer->host);
  761. if (error != error_data)
  762. bgp_notify_send_with_data (peer,
  763. BGP_NOTIFY_OPEN_ERR,
  764. BGP_NOTIFY_OPEN_UNSUP_CAPBL,
  765. error_data, error - error_data);
  766. else
  767. bgp_notify_send (peer,
  768. BGP_NOTIFY_OPEN_ERR,
  769. BGP_NOTIFY_OPEN_UNSUP_CAPBL);
  770. return -1;
  771. }
  772. }
  773. return 0;
  774. }
  775. static void
  776. bgp_open_capability_orf (struct stream *s, struct peer *peer,
  777. afi_t afi, safi_t safi, u_char code)
  778. {
  779. u_char cap_len;
  780. u_char orf_len;
  781. unsigned long capp;
  782. unsigned long orfp;
  783. unsigned long numberp;
  784. int number_of_orfs = 0;
  785. if (safi == SAFI_MPLS_VPN)
  786. safi = SAFI_MPLS_LABELED_VPN;
  787. stream_putc (s, BGP_OPEN_OPT_CAP);
  788. capp = stream_get_endp (s); /* Set Capability Len Pointer */
  789. stream_putc (s, 0); /* Capability Length */
  790. stream_putc (s, code); /* Capability Code */
  791. orfp = stream_get_endp (s); /* Set ORF Len Pointer */
  792. stream_putc (s, 0); /* ORF Length */
  793. stream_putw (s, afi);
  794. stream_putc (s, 0);
  795. stream_putc (s, safi);
  796. numberp = stream_get_endp (s); /* Set Number Pointer */
  797. stream_putc (s, 0); /* Number of ORFs */
  798. /* Address Prefix ORF */
  799. if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
  800. || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
  801. {
  802. stream_putc (s, (code == CAPABILITY_CODE_ORF ?
  803. ORF_TYPE_PREFIX : ORF_TYPE_PREFIX_OLD));
  804. if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
  805. && CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
  806. {
  807. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
  808. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
  809. stream_putc (s, ORF_MODE_BOTH);
  810. }
  811. else if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM))
  812. {
  813. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_SM_ADV);
  814. stream_putc (s, ORF_MODE_SEND);
  815. }
  816. else
  817. {
  818. SET_FLAG (peer->af_cap[afi][safi], PEER_CAP_ORF_PREFIX_RM_ADV);
  819. stream_putc (s, ORF_MODE_RECEIVE);
  820. }
  821. number_of_orfs++;
  822. }
  823. /* Total Number of ORFs. */
  824. stream_putc_at (s, numberp, number_of_orfs);
  825. /* Total ORF Len. */
  826. orf_len = stream_get_endp (s) - orfp - 1;
  827. stream_putc_at (s, orfp, orf_len);
  828. /* Total Capability Len. */
  829. cap_len = stream_get_endp (s) - capp - 1;
  830. stream_putc_at (s, capp, cap_len);
  831. }
  832. /* Fill in capability open option to the packet. */
  833. void
  834. bgp_open_capability (struct stream *s, struct peer *peer)
  835. {
  836. u_char len;
  837. unsigned long cp, capp, rcapp;
  838. afi_t afi;
  839. safi_t safi;
  840. as_t local_as;
  841. u_int32_t restart_time;
  842. /* Remember current pointer for Opt Parm Len. */
  843. cp = stream_get_endp (s);
  844. /* Opt Parm Len. */
  845. stream_putc (s, 0);
  846. /* Do not send capability. */
  847. if (! CHECK_FLAG (peer->sflags, PEER_STATUS_CAPABILITY_OPEN)
  848. || CHECK_FLAG (peer->flags, PEER_FLAG_DONT_CAPABILITY))
  849. return;
  850. /* IPv4 unicast. */
  851. if (peer->afc[AFI_IP][SAFI_UNICAST])
  852. {
  853. peer->afc_adv[AFI_IP][SAFI_UNICAST] = 1;
  854. stream_putc (s, BGP_OPEN_OPT_CAP);
  855. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  856. stream_putc (s, CAPABILITY_CODE_MP);
  857. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  858. stream_putw (s, AFI_IP);
  859. stream_putc (s, 0);
  860. stream_putc (s, SAFI_UNICAST);
  861. }
  862. /* IPv4 multicast. */
  863. if (peer->afc[AFI_IP][SAFI_MULTICAST])
  864. {
  865. peer->afc_adv[AFI_IP][SAFI_MULTICAST] = 1;
  866. stream_putc (s, BGP_OPEN_OPT_CAP);
  867. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  868. stream_putc (s, CAPABILITY_CODE_MP);
  869. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  870. stream_putw (s, AFI_IP);
  871. stream_putc (s, 0);
  872. stream_putc (s, SAFI_MULTICAST);
  873. }
  874. /* IPv4 VPN */
  875. if (peer->afc[AFI_IP][SAFI_MPLS_VPN])
  876. {
  877. peer->afc_adv[AFI_IP][SAFI_MPLS_VPN] = 1;
  878. stream_putc (s, BGP_OPEN_OPT_CAP);
  879. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  880. stream_putc (s, CAPABILITY_CODE_MP);
  881. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  882. stream_putw (s, AFI_IP);
  883. stream_putc (s, 0);
  884. stream_putc (s, SAFI_MPLS_LABELED_VPN);
  885. }
  886. /* ENCAP */
  887. if (peer->afc[AFI_IP][SAFI_ENCAP])
  888. {
  889. peer->afc_adv[AFI_IP][SAFI_ENCAP] = 1;
  890. stream_putc (s, BGP_OPEN_OPT_CAP);
  891. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  892. stream_putc (s, CAPABILITY_CODE_MP);
  893. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  894. stream_putw (s, AFI_IP);
  895. stream_putc (s, 0);
  896. stream_putc (s, SAFI_ENCAP);
  897. }
  898. /* IPv6 unicast. */
  899. if (peer->afc[AFI_IP6][SAFI_UNICAST])
  900. {
  901. peer->afc_adv[AFI_IP6][SAFI_UNICAST] = 1;
  902. stream_putc (s, BGP_OPEN_OPT_CAP);
  903. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  904. stream_putc (s, CAPABILITY_CODE_MP);
  905. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  906. stream_putw (s, AFI_IP6);
  907. stream_putc (s, 0);
  908. stream_putc (s, SAFI_UNICAST);
  909. }
  910. /* IPv6 multicast. */
  911. if (peer->afc[AFI_IP6][SAFI_MULTICAST])
  912. {
  913. peer->afc_adv[AFI_IP6][SAFI_MULTICAST] = 1;
  914. stream_putc (s, BGP_OPEN_OPT_CAP);
  915. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  916. stream_putc (s, CAPABILITY_CODE_MP);
  917. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  918. stream_putw (s, AFI_IP6);
  919. stream_putc (s, 0);
  920. stream_putc (s, SAFI_MULTICAST);
  921. }
  922. /* IPv6 VPN. */
  923. if (peer->afc[AFI_IP6][SAFI_MPLS_VPN])
  924. {
  925. peer->afc_adv[AFI_IP6][SAFI_MPLS_VPN] = 1;
  926. stream_putc (s, BGP_OPEN_OPT_CAP);
  927. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  928. stream_putc (s, CAPABILITY_CODE_MP);
  929. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  930. stream_putw (s, AFI_IP6);
  931. stream_putc (s, 0);
  932. stream_putc (s, SAFI_MPLS_LABELED_VPN);
  933. }
  934. /* IPv6 ENCAP. */
  935. if (peer->afc[AFI_IP6][SAFI_ENCAP])
  936. {
  937. peer->afc_adv[AFI_IP6][SAFI_ENCAP] = 1;
  938. stream_putc (s, BGP_OPEN_OPT_CAP);
  939. stream_putc (s, CAPABILITY_CODE_MP_LEN + 2);
  940. stream_putc (s, CAPABILITY_CODE_MP);
  941. stream_putc (s, CAPABILITY_CODE_MP_LEN);
  942. stream_putw (s, AFI_IP6);
  943. stream_putc (s, 0);
  944. stream_putc (s, SAFI_ENCAP);
  945. }
  946. /* Route refresh. */
  947. SET_FLAG (peer->cap, PEER_CAP_REFRESH_ADV);
  948. stream_putc (s, BGP_OPEN_OPT_CAP);
  949. stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
  950. stream_putc (s, CAPABILITY_CODE_REFRESH_OLD);
  951. stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
  952. stream_putc (s, BGP_OPEN_OPT_CAP);
  953. stream_putc (s, CAPABILITY_CODE_REFRESH_LEN + 2);
  954. stream_putc (s, CAPABILITY_CODE_REFRESH);
  955. stream_putc (s, CAPABILITY_CODE_REFRESH_LEN);
  956. /* AS4 */
  957. SET_FLAG (peer->cap, PEER_CAP_AS4_ADV);
  958. stream_putc (s, BGP_OPEN_OPT_CAP);
  959. stream_putc (s, CAPABILITY_CODE_AS4_LEN + 2);
  960. stream_putc (s, CAPABILITY_CODE_AS4);
  961. stream_putc (s, CAPABILITY_CODE_AS4_LEN);
  962. if ( peer->change_local_as )
  963. local_as = peer->change_local_as;
  964. else
  965. local_as = peer->local_as;
  966. stream_putl (s, local_as );
  967. /* ORF capability. */
  968. for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
  969. for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
  970. if (CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_SM)
  971. || CHECK_FLAG (peer->af_flags[afi][safi], PEER_FLAG_ORF_PREFIX_RM))
  972. {
  973. bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF_OLD);
  974. bgp_open_capability_orf (s, peer, afi, safi, CAPABILITY_CODE_ORF);
  975. }
  976. /* Dynamic capability. */
  977. if (CHECK_FLAG (peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
  978. {
  979. SET_FLAG (peer->cap, PEER_CAP_DYNAMIC_ADV);
  980. stream_putc (s, BGP_OPEN_OPT_CAP);
  981. stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN + 2);
  982. stream_putc (s, CAPABILITY_CODE_DYNAMIC);
  983. stream_putc (s, CAPABILITY_CODE_DYNAMIC_LEN);
  984. }
  985. /* Sending base graceful-restart capability irrespective of the config */
  986. SET_FLAG (peer->cap, PEER_CAP_RESTART_ADV);
  987. stream_putc (s, BGP_OPEN_OPT_CAP);
  988. capp = stream_get_endp (s); /* Set Capability Len Pointer */
  989. stream_putc (s, 0); /* Capability Length */
  990. stream_putc (s, CAPABILITY_CODE_RESTART);
  991. rcapp = stream_get_endp (s); /* Set Restart Capability Len Pointer */
  992. stream_putc (s, 0);
  993. restart_time = peer->bgp->restart_time;
  994. if (peer->bgp->t_startup)
  995. {
  996. SET_FLAG (restart_time, RESTART_R_BIT);
  997. SET_FLAG (peer->cap, PEER_CAP_RESTART_BIT_ADV);
  998. }
  999. stream_putw (s, restart_time);
  1000. /* Send address-family specific graceful-restart capability only when GR config
  1001. is present */
  1002. if (bgp_flag_check (peer->bgp, BGP_FLAG_GRACEFUL_RESTART))
  1003. {
  1004. for (afi = AFI_IP ; afi < AFI_MAX ; afi++)
  1005. for (safi = SAFI_UNICAST ; safi < SAFI_MAX ; safi++)
  1006. if (peer->afc[afi][safi])
  1007. {
  1008. stream_putw (s, afi);
  1009. stream_putc (s, safi);
  1010. stream_putc (s, 0); //Forwarding is not retained as of now.
  1011. }
  1012. }
  1013. /* Total Graceful restart capability Len. */
  1014. len = stream_get_endp (s) - rcapp - 1;
  1015. stream_putc_at (s, rcapp, len);
  1016. /* Total Capability Len. */
  1017. len = stream_get_endp (s) - capp - 1;
  1018. stream_putc_at (s, capp, len);
  1019. /* Total Opt Parm Len. */
  1020. len = stream_get_endp (s) - cp - 1;
  1021. stream_putc_at (s, cp, len);
  1022. }