PageRenderTime 27ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 1ms

/release/src/router/zebra/bgpd/bgp_tcpsig.c

https://gitlab.com/envieidoc/advancedtomato2
C | 573 lines | 440 code | 112 blank | 21 comment | 82 complexity | 683b9c48e05a42a5163299e3ed9a70ee MD5 | raw file
  1. /* BGP TCP signature related functions
  2. Copyright (C) 2004 Hiroki Nakano; Thanks to Okabe lab. (Kyoto University)
  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. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  18. #include <net/pfkeyv2.h>
  19. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
  20. #include "log.h"
  21. #include "memory.h"
  22. #include "sockunion.h"
  23. #include "vty.h"
  24. #include "bgpd/bgpd.h"
  25. #include "bgpd/bgp_network.h"
  26. #include "bgpd/bgp_tcpsig.h"
  27. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  28. #define IOVEC_SIZE 20
  29. #define MAX_KEY_LEN 80
  30. #define SADBALIGN sizeof(u_int64_t)
  31. #define LENUNIT(x) ((x) / SADBALIGN)
  32. #define EXTLEN(x) (((struct sadb_ext *)(x))->sadb_ext_len * SADBALIGN)
  33. #define PADUP(x) (((x) + (SADBALIGN - 1)) & ~(SADBALIGN - 1))
  34. static u_int32_t bgp_pfkey_sadb_msg_seq = 1;
  35. static int bgp_pfkey_sd = -1;
  36. int bgp_pfkey_init(void);
  37. #define PUSH_IOVEC(base,len) ((*iovsizep) > 0 ? \
  38. ((*iovp)->iov_base = (base), \
  39. (*iovp)->iov_len = (len), \
  40. (*iovp)++, \
  41. (*iovsizep)--) : \
  42. ((*iovsizep) = -1))
  43. struct bgp_pfkey_sadb_msg {
  44. struct sadb_msg header;
  45. };
  46. int
  47. bgp_pfkey_build_sadb_msg(u_int8_t mtype,
  48. struct bgp_pfkey_sadb_msg *sp,
  49. struct iovec **iovp, int *iovsizep)
  50. {
  51. memset(sp, 0, sizeof(*sp));
  52. sp->header.sadb_msg_version = PF_KEY_V2;
  53. sp->header.sadb_msg_type = mtype;
  54. sp->header.sadb_msg_satype = SADB_X_SATYPE_TCPSIGNATURE;
  55. sp->header.sadb_msg_len = LENUNIT(sizeof(sp->header));
  56. sp->header.sadb_msg_seq = bgp_pfkey_sadb_msg_seq++;
  57. sp->header.sadb_msg_pid = getpid();
  58. PUSH_IOVEC(&sp->header, sizeof(sp->header));
  59. return sp->header.sadb_msg_len;
  60. }
  61. struct bgp_pfkey_sadb_sa {
  62. struct sadb_sa header;
  63. };
  64. int
  65. bgp_pfkey_build_sadb_sa(u_int32_t spi,
  66. struct bgp_pfkey_sadb_sa *sp,
  67. struct iovec **iovp, int *iovsizep)
  68. {
  69. memset(sp, 0, sizeof(*sp));
  70. sp->header.sadb_sa_len = LENUNIT(sizeof(sp->header));
  71. sp->header.sadb_sa_exttype = SADB_EXT_SA;
  72. sp->header.sadb_sa_spi = spi;
  73. sp->header.sadb_sa_replay = 0;
  74. sp->header.sadb_sa_state = SADB_SASTATE_MATURE;
  75. sp->header.sadb_sa_auth = 0;
  76. sp->header.sadb_sa_encrypt = 0;
  77. PUSH_IOVEC(&sp->header, sizeof(sp->header));
  78. return sp->header.sadb_sa_len;
  79. }
  80. struct bgp_pfkey_sadb_address {
  81. struct sadb_address header;
  82. struct sockaddr_storage ss;
  83. };
  84. int
  85. bgp_pfkey_build_sadb_address(union sockunion *su,
  86. struct bgp_pfkey_sadb_address *sp,
  87. struct iovec **iovp, int *iovsizep)
  88. {
  89. int paddedsslen;
  90. memset(sp, 0, sizeof(*sp));
  91. switch (su->sa.sa_family) {
  92. case AF_INET:
  93. ((struct sockaddr_in *)&sp->ss)->sin_family = AF_INET;
  94. ((struct sockaddr_in *)&sp->ss)->sin_len = sizeof(struct sockaddr_in);
  95. ((struct sockaddr_in *)&sp->ss)->sin_addr = su->sin.sin_addr;
  96. break;
  97. case AF_INET6:
  98. ((struct sockaddr_in6 *)&sp->ss)->sin6_family = AF_INET6;
  99. ((struct sockaddr_in6 *)&sp->ss)->sin6_len = sizeof(struct sockaddr_in6);
  100. ((struct sockaddr_in6 *)&sp->ss)->sin6_addr = su->sin6.sin6_addr;
  101. break;
  102. default:
  103. return -1;
  104. }
  105. paddedsslen = PADUP(((struct sockaddr *)&sp->ss)->sa_len);
  106. sp->header.sadb_address_len = LENUNIT(sizeof(sp->header) + paddedsslen);
  107. sp->header.sadb_address_exttype = SADB_EXT_ADDRESS_SRC;
  108. PUSH_IOVEC(&sp->header, sizeof(sp->header));
  109. PUSH_IOVEC(&sp->ss, paddedsslen);
  110. return sp->header.sadb_address_len;
  111. }
  112. struct bgp_pfkey_sadb_key {
  113. struct sadb_key header;
  114. char keybuf[PADUP(MAX_KEY_LEN)];
  115. };
  116. int
  117. bgp_pfkey_build_sadb_key(char *key, int keylen,
  118. struct bgp_pfkey_sadb_key *sp,
  119. struct iovec **iovp, int *iovsizep)
  120. {
  121. int paddedkeylen;
  122. if (keylen < 0 || keylen > MAX_KEY_LEN)
  123. return -1;
  124. memset(sp, 0, sizeof(*sp));
  125. memcpy(sp->keybuf, key, keylen);
  126. paddedkeylen = PADUP(keylen);
  127. sp->header.sadb_key_len = LENUNIT(sizeof(sp->header) + paddedkeylen);
  128. sp->header.sadb_key_exttype = SADB_EXT_KEY_AUTH;
  129. sp->header.sadb_key_bits = 8 * keylen;
  130. PUSH_IOVEC(&sp->header, sizeof(sp->header));
  131. PUSH_IOVEC(sp->keybuf, paddedkeylen);
  132. return sp->header.sadb_key_len;
  133. }
  134. struct bgp_pfkey_sadb_spirange {
  135. struct sadb_spirange header;
  136. };
  137. int
  138. bgp_pfkey_build_sadb_spirange(struct bgp_pfkey_sadb_spirange *sp,
  139. struct iovec **iovp, int *iovsizep)
  140. {
  141. memset(sp, 0, sizeof(*sp));
  142. sp->header.sadb_spirange_len = LENUNIT(sizeof(sp->header));
  143. sp->header.sadb_spirange_exttype = SADB_EXT_SPIRANGE;
  144. sp->header.sadb_spirange_min = 0x100;
  145. sp->header.sadb_spirange_max = 0xffffffff;
  146. PUSH_IOVEC(&sp->header, sizeof(sp->header));
  147. return sp->header.sadb_spirange_len;
  148. }
  149. int
  150. bgp_pfkey_write(int fd, struct iovec *iov, int iovcnt)
  151. {
  152. int i, len, rlen;
  153. len = 0;
  154. for (i = 0; i < iovcnt; i++)
  155. len += iov[i].iov_len;
  156. rlen = writev(fd, iov, iovcnt);
  157. if (rlen == -1)
  158. {
  159. zlog_err("pfkey writev: %s", strerror(errno));
  160. return -1;
  161. }
  162. else if (rlen != len)
  163. {
  164. zlog_err("pfkey writev: len=%d ret=%d", len, rlen);
  165. return -1;
  166. }
  167. return 0;
  168. }
  169. int
  170. bgp_pfkey_read(int fd, void **bufp, int *lenp)
  171. {
  172. struct sadb_msg smsg;
  173. void *msgbuf;
  174. int msglen, rlen;
  175. rlen = recv(fd, &smsg, sizeof(smsg), MSG_PEEK);
  176. if (rlen == -1)
  177. {
  178. zlog_err("pfkey recv: %s", strerror(errno));
  179. return -1;
  180. }
  181. if (rlen != sizeof(smsg))
  182. {
  183. zlog_err("pfkey recv: len=%d ret=%d", sizeof(smsg), rlen);
  184. return -1;
  185. }
  186. if (smsg.sadb_msg_errno != 0 ||
  187. smsg.sadb_msg_errno != ESRCH)
  188. {
  189. zlog_err("pfkey read msg: %s", strerror(smsg.sadb_msg_errno));
  190. read(fd, &smsg, sizeof(smsg)); /* get rid of error message */
  191. return -1;
  192. }
  193. msglen = smsg.sadb_msg_len * SADBALIGN;
  194. msgbuf = XMALLOC(MTYPE_TMP, msglen);
  195. rlen = read(fd, msgbuf, msglen);
  196. if (rlen == -1)
  197. {
  198. zlog_err("pfkey read: %s", strerror(errno));
  199. XFREE(MTYPE_TMP, msgbuf);
  200. return -1;
  201. }
  202. if (rlen != msglen)
  203. {
  204. zlog_err("pfkey read: len=%d ret=%d", msglen, rlen);
  205. XFREE(MTYPE_TMP, msgbuf);
  206. return -1;
  207. }
  208. *bufp = msgbuf;
  209. *lenp = msglen;
  210. return 0;
  211. }
  212. int
  213. bgp_pfkey_search_ext(void *buf, u_int16_t exttype, void **prevp)
  214. {
  215. struct sadb_msg *msg;
  216. struct sadb_ext *p, *last;
  217. u_int32_t len;
  218. msg = buf;
  219. len = msg->sadb_msg_len * SADBALIGN;
  220. last = (struct sadb_ext *)(((u_int8_t *)msg) + len);
  221. p = *prevp ? *prevp : (struct sadb_ext *)(msg + 1);
  222. while ((u_int8_t *)p < (u_int8_t *)last)
  223. {
  224. if (p->sadb_ext_type == exttype)
  225. {
  226. *prevp = p;
  227. return 0; /* found */
  228. }
  229. p = (struct sadb_ext *)(((u_int8_t *)p) + EXTLEN(p));
  230. }
  231. return -1; /* not found */
  232. }
  233. int
  234. bgp_pfkey_getspi(union sockunion *src, union sockunion *dst, u_int32_t *spip)
  235. {
  236. struct iovec iovbuf[IOVEC_SIZE], *iov;
  237. int iovcnt, iovrest;
  238. struct bgp_pfkey_sadb_msg s_msg;
  239. struct bgp_pfkey_sadb_spirange s_spirange;
  240. struct bgp_pfkey_sadb_address s_srcaddr, s_dstaddr;
  241. int len;
  242. void *buf;
  243. int buflen;
  244. struct sadb_sa *ext_sa;
  245. if (bgp_pfkey_sd == -1)
  246. {
  247. bgp_pfkey_init();
  248. if (bgp_pfkey_sd == -1)
  249. return -1;
  250. }
  251. iov = iovbuf;
  252. iovcnt = iovrest = sizeof(iov) / sizeof(iov[0]);
  253. len = bgp_pfkey_build_sadb_msg(SADB_GETSPI, &s_msg, &iov, &iovrest);
  254. len += bgp_pfkey_build_sadb_spirange(&s_spirange, &iov, &iovrest);
  255. len += bgp_pfkey_build_sadb_address(dst, &s_dstaddr, &iov, &iovrest);
  256. len += bgp_pfkey_build_sadb_address(src, &s_srcaddr, &iov, &iovrest);
  257. s_msg.header.sadb_msg_len = len;
  258. iovcnt -= iovrest;
  259. if (bgp_pfkey_write(bgp_pfkey_sd, iov, iovcnt) != 0)
  260. {
  261. zlog_err("pfkey getspi: fail to write request");
  262. return -1;
  263. }
  264. if (bgp_pfkey_read(bgp_pfkey_sd, &buf, &buflen) != 0)
  265. {
  266. zlog_err("pfkey getspi: fail to read reply");
  267. return -1;
  268. }
  269. if (bgp_pfkey_search_ext(buf, SADB_EXT_SA, (void **)&ext_sa) != 0)
  270. {
  271. zlog_err("pfkey getspi: no SA extention");
  272. XFREE(MTYPE_TMP, buf);
  273. return -1;
  274. }
  275. *spip = ext_sa->sadb_sa_spi;
  276. XFREE(MTYPE_TMP, buf);
  277. return 0;
  278. }
  279. int
  280. bgp_pfkey_update(u_int32_t spi, union sockunion *src, union sockunion *dst,
  281. char *key)
  282. {
  283. struct iovec iovbuf[IOVEC_SIZE], *iov;
  284. int iovcnt, iovrest;
  285. struct bgp_pfkey_sadb_msg s_msg;
  286. struct bgp_pfkey_sadb_sa s_sa;
  287. struct bgp_pfkey_sadb_address s_srcaddr, s_dstaddr;
  288. struct bgp_pfkey_sadb_key s_key;
  289. int len;
  290. void *buf;
  291. int buflen;
  292. if (bgp_pfkey_sd == -1)
  293. {
  294. bgp_pfkey_init();
  295. if (bgp_pfkey_sd == -1)
  296. return -1;
  297. }
  298. iov = iovbuf;
  299. iovcnt = iovrest = sizeof(iov) / sizeof(iov[0]);
  300. len = bgp_pfkey_build_sadb_msg(SADB_UPDATE, &s_msg, &iov, &iovrest);
  301. len += bgp_pfkey_build_sadb_sa(spi, &s_sa, &iov, &iovrest);
  302. len += bgp_pfkey_build_sadb_address(dst, &s_dstaddr, &iov, &iovrest);
  303. len += bgp_pfkey_build_sadb_address(src, &s_srcaddr, &iov, &iovrest);
  304. len += bgp_pfkey_build_sadb_key(key, strlen(key), &s_key, &iov, &iovrest);
  305. s_msg.header.sadb_msg_len = len;
  306. iovcnt -= iovrest;
  307. if (bgp_pfkey_write(bgp_pfkey_sd, iov, iovcnt) != 0)
  308. {
  309. zlog_err("pfkey update: fail to write request");
  310. return -1;
  311. }
  312. if (bgp_pfkey_read(bgp_pfkey_sd, &buf, &buflen) != 0)
  313. {
  314. zlog_err("pfkey update: fail to read reply");
  315. return -1;
  316. }
  317. XFREE(MTYPE_TMP, buf);
  318. return 0;
  319. }
  320. int
  321. bgp_pfkey_delete(u_int32_t spi, union sockunion *src, union sockunion *dst)
  322. {
  323. struct iovec iovbuf[IOVEC_SIZE], *iov;
  324. int iovcnt, iovrest;
  325. struct bgp_pfkey_sadb_msg s_msg;
  326. struct bgp_pfkey_sadb_sa s_sa;
  327. struct bgp_pfkey_sadb_address s_srcaddr, s_dstaddr;
  328. int len;
  329. void *buf;
  330. int buflen;
  331. if (bgp_pfkey_sd == -1)
  332. {
  333. bgp_pfkey_init();
  334. if (bgp_pfkey_sd == -1)
  335. return -1;
  336. }
  337. iov = iovbuf;
  338. iovcnt = iovrest = sizeof(iov) / sizeof(iov[0]);
  339. len = bgp_pfkey_build_sadb_msg(SADB_DELETE, &s_msg, &iov, &iovrest);
  340. len += bgp_pfkey_build_sadb_sa(spi, &s_sa, &iov, &iovrest);
  341. len += bgp_pfkey_build_sadb_address(dst, &s_dstaddr, &iov, &iovrest);
  342. len += bgp_pfkey_build_sadb_address(src, &s_srcaddr, &iov, &iovrest);
  343. s_msg.header.sadb_msg_len = len;
  344. iovcnt -= iovrest;
  345. if (bgp_pfkey_write(bgp_pfkey_sd, iov, iovcnt) != 0)
  346. {
  347. zlog_err("pfkey delete: fail to write request");
  348. return -1;
  349. }
  350. if (bgp_pfkey_read(bgp_pfkey_sd, &buf, &buflen) != 0)
  351. {
  352. zlog_err("pfkey delete: fail to read reply");
  353. return -1;
  354. }
  355. XFREE(MTYPE_TMP, buf);
  356. return 0;
  357. }
  358. int
  359. bgp_pfkey_init(void)
  360. {
  361. bgp_pfkey_sd = socket(PF_KEY, SOCK_RAW, PF_KEY_V2);
  362. if (bgp_pfkey_sd == -1)
  363. {
  364. zlog_warn("pfkey socket: %s", strerror(errno));
  365. return -1;
  366. }
  367. return 0;
  368. }
  369. /*----------------------------------------------------------------*/
  370. int
  371. bgp_tcpsig_pfkey_set(struct peer *p)
  372. {
  373. if (!p->update_source)
  374. return -1;
  375. if (p->spi_out == 0)
  376. if (bgp_pfkey_getspi(p->update_source, &p->su, &p->spi_out) != 0)
  377. return -1;
  378. if (bgp_pfkey_update(p->spi_out,
  379. p->update_source, &p->su, p->password) != 0)
  380. return -1;
  381. if (p->spi_in == 0)
  382. if (bgp_pfkey_getspi(&p->su, p->update_source, &p->spi_in) != 0)
  383. return -1;
  384. if (bgp_pfkey_update(p->spi_in,
  385. &p->su, p->update_source, p->password) != 0)
  386. return -1;
  387. return 0;
  388. }
  389. int
  390. bgp_tcpsig_pfkey_unset(struct peer *p)
  391. {
  392. if (!p->update_source)
  393. return -1;
  394. if (p->spi_out != 0)
  395. if (bgp_pfkey_delete(p->spi_out, p->update_source, &p->su) != 0)
  396. return -1;
  397. p->spi_out = 0;
  398. if (p->spi_in != 0)
  399. if (bgp_pfkey_delete(p->spi_in, &p->su, p->update_source) != 0)
  400. return -1;
  401. p->spi_in = 0;
  402. return 0;
  403. }
  404. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
  405. /*----------------------------------------------------------------*/
  406. #ifdef HAVE_LINUX_TCP_SIGNATURE
  407. int
  408. bgp_tcpsig_set (int sock, struct peer *peer)
  409. {
  410. struct tcp_rfc2385_cmd cmd;
  411. int ret;
  412. if (sockunion_family (&peer->su) != AF_INET)
  413. return 0; /* XXX */
  414. cmd.command = TCP_MD5_AUTH_ADD;
  415. cmd.address = peer->su.sin.sin_addr.s_addr;
  416. cmd.keylen = strlen (peer->password);
  417. cmd.key = peer->password;
  418. ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
  419. return ret;
  420. }
  421. #endif /* HAVE_LINUX_TCP_SIGNATURE */
  422. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  423. int
  424. bgp_tcpsig_set (int sock, struct peer *peer)
  425. {
  426. int cmd = 1;
  427. int ret = 0;
  428. if (peer)
  429. ret = bgp_tcpsig_pfkey_set(peer);
  430. if (ret == 0 && sock != -1)
  431. ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5SIG, &cmd, sizeof cmd);
  432. return ret;
  433. }
  434. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */
  435. #ifdef HAVE_LINUX_TCP_SIGNATURE
  436. int
  437. bgp_tcpsig_unset (int sock, struct peer *peer)
  438. {
  439. struct tcp_rfc2385_cmd cmd;
  440. int ret;
  441. if (sockunion_family (&peer->su) != AF_INET)
  442. return 0; /* XXX */
  443. cmd.command = TCP_MD5_AUTH_DEL;
  444. cmd.address = peer->su.sin.sin_addr.s_addr;
  445. cmd.keylen = strlen (peer->password);
  446. cmd.key = peer->password;
  447. ret = setsockopt (sock, IPPROTO_TCP, TCP_MD5_AUTH, &cmd, sizeof cmd);
  448. return ret;
  449. }
  450. #endif /* HAVE_LINUX_TCP_SIGNATURE */
  451. #ifdef HAVE_OPENBSD_TCP_SIGNATURE
  452. int
  453. bgp_tcpsig_unset (int sock, struct peer *peer)
  454. {
  455. return bgp_tcpsig_pfkey_unset(peer);
  456. }
  457. #endif /* HAVE_OPENBSD_TCP_SIGNATURE */