if_gre.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774
  1. /* $OpenBSD: if_gre.c,v 1.75 2015/07/16 16:12:15 mpi Exp $ */
  2. /* $NetBSD: if_gre.c,v 1.9 1999/10/25 19:18:11 drochner Exp $ */
  3. /*
  4. * Copyright (c) 1998 The NetBSD Foundation, Inc.
  5. * All rights reserved.
  6. *
  7. * This code is derived from software contributed to The NetBSD Foundation
  8. * by Heiko W.Rupp <hwr@pilhuhn.de>
  9. *
  10. * IPv6-over-GRE contributed by Gert Doering <gert@greenie.muc.de>
  11. *
  12. * Redistribution and use in source and binary forms, with or without
  13. * modification, are permitted provided that the following conditions
  14. * are met:
  15. * 1. Redistributions of source code must retain the above copyright
  16. * notice, this list of conditions and the following disclaimer.
  17. * 2. Redistributions in binary form must reproduce the above copyright
  18. * notice, this list of conditions and the following disclaimer in the
  19. * documentation and/or other materials provided with the distribution.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
  22. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
  23. * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  24. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
  25. * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  26. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  27. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  28. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  29. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  30. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  31. * POSSIBILITY OF SUCH DAMAGE.
  32. */
  33. /*
  34. * Encapsulate L3 protocols into IP, per RFC 1701 and 1702.
  35. * See gre(4) for more details.
  36. * Also supported: IP in IP encapsulation (proto 55) per RFC 2004.
  37. */
  38. #include "gre.h"
  39. #if NGRE > 0
  40. #include "bpfilter.h"
  41. #include "pf.h"
  42. #include <sys/param.h>
  43. #include <sys/mbuf.h>
  44. #include <sys/socket.h>
  45. #include <sys/sockio.h>
  46. #include <sys/kernel.h>
  47. #include <sys/systm.h>
  48. #include <sys/timeout.h>
  49. #include <net/if.h>
  50. #include <net/if_types.h>
  51. #include <net/route.h>
  52. #include <netinet/in.h>
  53. #include <netinet/ip.h>
  54. #include <netinet/ip_var.h>
  55. #include <netinet/if_ether.h>
  56. #if NBPFILTER > 0
  57. #include <net/bpf.h>
  58. #endif
  59. #if NPF > 0
  60. #include <net/pfvar.h>
  61. #endif
  62. #include <net/if_gre.h>
  63. #ifndef GRE_RECURSION_LIMIT
  64. #define GRE_RECURSION_LIMIT 3 /* How many levels of recursion allowed */
  65. #endif /* GRE_RECURSION_LIMIT */
  66. /*
  67. * It is not easy to calculate the right value for a GRE MTU.
  68. * We leave this task to the admin and use the same default that
  69. * other vendors use.
  70. */
  71. #define GREMTU 1476
  72. int gre_clone_create(struct if_clone *, int);
  73. int gre_clone_destroy(struct ifnet *);
  74. struct gre_softc_head gre_softc_list;
  75. struct if_clone gre_cloner =
  76. IF_CLONE_INITIALIZER("gre", gre_clone_create, gre_clone_destroy);
  77. /*
  78. * We can control the acceptance of GRE and MobileIP packets by
  79. * altering the sysctl net.inet.gre.allow and net.inet.mobileip.allow values
  80. * respectively. Zero means drop them, all else is acceptance. We can also
  81. * control acceptance of WCCPv1-style GRE packets through the
  82. * net.inet.gre.wccp value, but be aware it depends upon normal GRE being
  83. * allowed as well.
  84. *
  85. */
  86. int gre_allow = 0;
  87. int gre_wccp = 0;
  88. int ip_mobile_allow = 0;
  89. void gre_keepalive(void *);
  90. void gre_send_keepalive(void *);
  91. void gre_link_state(struct gre_softc *);
  92. void
  93. greattach(int n)
  94. {
  95. LIST_INIT(&gre_softc_list);
  96. if_clone_attach(&gre_cloner);
  97. }
  98. int
  99. gre_clone_create(struct if_clone *ifc, int unit)
  100. {
  101. struct gre_softc *sc;
  102. int s;
  103. sc = malloc(sizeof(*sc), M_DEVBUF, M_NOWAIT|M_ZERO);
  104. if (!sc)
  105. return (ENOMEM);
  106. snprintf(sc->sc_if.if_xname, sizeof sc->sc_if.if_xname, "%s%d",
  107. ifc->ifc_name, unit);
  108. sc->sc_if.if_softc = sc;
  109. sc->sc_if.if_type = IFT_TUNNEL;
  110. sc->sc_if.if_addrlen = 0;
  111. sc->sc_if.if_hdrlen = 24; /* IP + GRE */
  112. sc->sc_if.if_mtu = GREMTU;
  113. sc->sc_if.if_flags = IFF_POINTOPOINT|IFF_MULTICAST;
  114. sc->sc_if.if_output = gre_output;
  115. sc->sc_if.if_ioctl = gre_ioctl;
  116. sc->sc_if.if_collisions = 0;
  117. sc->sc_if.if_ierrors = 0;
  118. sc->sc_if.if_oerrors = 0;
  119. sc->sc_if.if_ipackets = 0;
  120. sc->sc_if.if_opackets = 0;
  121. sc->g_dst.s_addr = sc->g_src.s_addr = INADDR_ANY;
  122. sc->g_proto = IPPROTO_GRE;
  123. sc->sc_if.if_flags |= IFF_LINK0;
  124. sc->sc_ka_state = GRE_STATE_UKNWN;
  125. timeout_set(&sc->sc_ka_hold, gre_keepalive, sc);
  126. timeout_set(&sc->sc_ka_snd, gre_send_keepalive, sc);
  127. if_attach(&sc->sc_if);
  128. if_alloc_sadl(&sc->sc_if);
  129. #if NBPFILTER > 0
  130. bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_LOOP, sizeof(u_int32_t));
  131. #endif
  132. s = splnet();
  133. LIST_INSERT_HEAD(&gre_softc_list, sc, sc_list);
  134. splx(s);
  135. return (0);
  136. }
  137. int
  138. gre_clone_destroy(struct ifnet *ifp)
  139. {
  140. struct gre_softc *sc = ifp->if_softc;
  141. int s;
  142. s = splnet();
  143. timeout_del(&sc->sc_ka_snd);
  144. timeout_del(&sc->sc_ka_hold);
  145. LIST_REMOVE(sc, sc_list);
  146. splx(s);
  147. if_detach(ifp);
  148. free(sc, M_DEVBUF, sizeof(*sc));
  149. return (0);
  150. }
  151. /*
  152. * The output routine. Takes a packet and encapsulates it in the protocol
  153. * given by sc->g_proto. See also RFC 1701 and RFC 2004.
  154. */
  155. int
  156. gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
  157. struct rtentry *rt)
  158. {
  159. int error = 0;
  160. struct gre_softc *sc = (struct gre_softc *) (ifp->if_softc);
  161. struct greip *gh = NULL;
  162. struct ip *inp = NULL;
  163. u_int8_t ip_tos = 0;
  164. u_int16_t etype = 0;
  165. struct mobile_h mob_h;
  166. struct m_tag *mtag;
  167. if ((ifp->if_flags & IFF_UP) == 0 ||
  168. sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY) {
  169. m_freem(m);
  170. error = ENETDOWN;
  171. goto end;
  172. }
  173. #ifdef DIAGNOSTIC
  174. if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.ph_rtableid)) {
  175. printf("%s: trying to send packet on wrong domain. "
  176. "if %d vs. mbuf %d, AF %d\n", ifp->if_xname,
  177. ifp->if_rdomain, rtable_l2(m->m_pkthdr.ph_rtableid),
  178. dst->sa_family);
  179. }
  180. #endif
  181. /* Try to limit infinite recursion through misconfiguration. */
  182. for (mtag = m_tag_find(m, PACKET_TAG_GRE, NULL); mtag;
  183. mtag = m_tag_find(m, PACKET_TAG_GRE, mtag)) {
  184. if (!bcmp((caddr_t)(mtag + 1), &ifp, sizeof(struct ifnet *))) {
  185. IF_DROP(&ifp->if_snd);
  186. m_freem(m);
  187. error = EIO;
  188. goto end;
  189. }
  190. }
  191. mtag = m_tag_get(PACKET_TAG_GRE, sizeof(struct ifnet *), M_NOWAIT);
  192. if (mtag == NULL) {
  193. IF_DROP(&ifp->if_snd);
  194. m_freem(m);
  195. error = ENOBUFS;
  196. goto end;
  197. }
  198. bcopy(&ifp, (caddr_t)(mtag + 1), sizeof(struct ifnet *));
  199. m_tag_prepend(m, mtag);
  200. m->m_flags &= ~(M_BCAST|M_MCAST);
  201. #if NBPFILTER > 0
  202. if (ifp->if_bpf)
  203. bpf_mtap_af(ifp->if_bpf, dst->sa_family, m, BPF_DIRECTION_OUT);
  204. #endif
  205. if (sc->g_proto == IPPROTO_MOBILE) {
  206. if (ip_mobile_allow == 0) {
  207. IF_DROP(&ifp->if_snd);
  208. m_freem(m);
  209. error = EACCES;
  210. goto end;
  211. }
  212. if (dst->sa_family == AF_INET) {
  213. struct mbuf *m0;
  214. int msiz;
  215. /*
  216. * Make sure the complete IP header (with options)
  217. * is in the first mbuf.
  218. */
  219. if (m->m_len < sizeof(struct ip)) {
  220. m = m_pullup(m, sizeof(struct ip));
  221. if (m == NULL) {
  222. IF_DROP(&ifp->if_snd);
  223. error = ENOBUFS;
  224. goto end;
  225. } else
  226. inp = mtod(m, struct ip *);
  227. if (m->m_len < inp->ip_hl << 2) {
  228. m = m_pullup(m, inp->ip_hl << 2);
  229. if (m == NULL) {
  230. IF_DROP(&ifp->if_snd);
  231. error = ENOBUFS;
  232. goto end;
  233. }
  234. }
  235. }
  236. inp = mtod(m, struct ip *);
  237. bzero(&mob_h, MOB_H_SIZ_L);
  238. mob_h.proto = (inp->ip_p) << 8;
  239. mob_h.odst = inp->ip_dst.s_addr;
  240. inp->ip_dst.s_addr = sc->g_dst.s_addr;
  241. /*
  242. * If the packet comes from our host, we only change
  243. * the destination address in the IP header.
  244. * Otherwise we need to save and change the source.
  245. */
  246. if (inp->ip_src.s_addr == sc->g_src.s_addr) {
  247. msiz = MOB_H_SIZ_S;
  248. } else {
  249. mob_h.proto |= MOB_H_SBIT;
  250. mob_h.osrc = inp->ip_src.s_addr;
  251. inp->ip_src.s_addr = sc->g_src.s_addr;
  252. msiz = MOB_H_SIZ_L;
  253. }
  254. mob_h.proto = htons(mob_h.proto);
  255. mob_h.hcrc = gre_in_cksum((u_int16_t *) &mob_h, msiz);
  256. /* Squeeze in the mobility header */
  257. if ((m->m_data - msiz) < m->m_pktdat) {
  258. /* Need new mbuf */
  259. MGETHDR(m0, M_DONTWAIT, MT_HEADER);
  260. if (m0 == NULL) {
  261. IF_DROP(&ifp->if_snd);
  262. m_freem(m);
  263. error = ENOBUFS;
  264. goto end;
  265. }
  266. M_MOVE_HDR(m0, m);
  267. m0->m_len = msiz + (inp->ip_hl << 2);
  268. m0->m_data += max_linkhdr;
  269. m0->m_pkthdr.len = m->m_pkthdr.len + msiz;
  270. m->m_data += inp->ip_hl << 2;
  271. m->m_len -= inp->ip_hl << 2;
  272. bcopy((caddr_t) inp, mtod(m0, caddr_t),
  273. sizeof(struct ip));
  274. m0->m_next = m;
  275. m = m0;
  276. } else { /* we have some space left in the old one */
  277. m->m_data -= msiz;
  278. m->m_len += msiz;
  279. m->m_pkthdr.len += msiz;
  280. bcopy(inp, mtod(m, caddr_t),
  281. inp->ip_hl << 2);
  282. }
  283. /* Copy Mobility header */
  284. inp = mtod(m, struct ip *);
  285. bcopy(&mob_h, (caddr_t)(inp + 1), (unsigned) msiz);
  286. inp->ip_len = htons(ntohs(inp->ip_len) + msiz);
  287. } else { /* AF_INET */
  288. IF_DROP(&ifp->if_snd);
  289. m_freem(m);
  290. error = EINVAL;
  291. goto end;
  292. }
  293. } else if (sc->g_proto == IPPROTO_GRE) {
  294. if (gre_allow == 0) {
  295. IF_DROP(&ifp->if_snd);
  296. m_freem(m);
  297. error = EACCES;
  298. goto end;
  299. }
  300. switch(dst->sa_family) {
  301. case AF_INET:
  302. if (m->m_len < sizeof(struct ip)) {
  303. m = m_pullup(m, sizeof(struct ip));
  304. if (m == NULL) {
  305. IF_DROP(&ifp->if_snd);
  306. error = ENOBUFS;
  307. goto end;
  308. }
  309. }
  310. inp = mtod(m, struct ip *);
  311. ip_tos = inp->ip_tos;
  312. etype = ETHERTYPE_IP;
  313. break;
  314. #ifdef INET6
  315. case AF_INET6:
  316. etype = ETHERTYPE_IPV6;
  317. break;
  318. #endif
  319. #ifdef MPLS
  320. case AF_MPLS:
  321. if (m->m_flags & (M_BCAST | M_MCAST))
  322. etype = ETHERTYPE_MPLS_MCAST;
  323. else
  324. etype = ETHERTYPE_MPLS;
  325. break;
  326. #endif
  327. default:
  328. IF_DROP(&ifp->if_snd);
  329. m_freem(m);
  330. error = EAFNOSUPPORT;
  331. goto end;
  332. }
  333. M_PREPEND(m, sizeof(struct greip), M_DONTWAIT);
  334. } else {
  335. IF_DROP(&ifp->if_snd);
  336. m_freem(m);
  337. error = EINVAL;
  338. goto end;
  339. }
  340. if (m == NULL) {
  341. IF_DROP(&ifp->if_snd);
  342. error = ENOBUFS;
  343. goto end;
  344. }
  345. gh = mtod(m, struct greip *);
  346. if (sc->g_proto == IPPROTO_GRE) {
  347. /* We don't support any GRE flags for now */
  348. bzero((void *) &gh->gi_g, sizeof(struct gre_h));
  349. gh->gi_ptype = htons(etype);
  350. }
  351. gh->gi_pr = sc->g_proto;
  352. if (sc->g_proto != IPPROTO_MOBILE) {
  353. gh->gi_src = sc->g_src;
  354. gh->gi_dst = sc->g_dst;
  355. ((struct ip *) gh)->ip_hl = (sizeof(struct ip)) >> 2;
  356. ((struct ip *) gh)->ip_ttl = ip_defttl;
  357. ((struct ip *) gh)->ip_tos = ip_tos;
  358. gh->gi_len = htons(m->m_pkthdr.len);
  359. }
  360. ifp->if_opackets++;
  361. ifp->if_obytes += m->m_pkthdr.len;
  362. m->m_pkthdr.ph_rtableid = sc->g_rtableid;
  363. #if NPF > 0
  364. pf_pkt_addr_changed(m);
  365. #endif
  366. /* Send it off */
  367. error = ip_output(m, NULL, &sc->route, 0, NULL, NULL, 0);
  368. end:
  369. if (error)
  370. ifp->if_oerrors++;
  371. return (error);
  372. }
  373. int
  374. gre_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
  375. {
  376. struct ifreq *ifr = (struct ifreq *)data;
  377. struct ifaddr *ifa = (struct ifaddr *)data;
  378. struct if_laddrreq *lifr = (struct if_laddrreq *)data;
  379. struct ifkalivereq *ikar = (struct ifkalivereq *)data;
  380. struct gre_softc *sc = ifp->if_softc;
  381. int s;
  382. struct sockaddr_in si;
  383. struct sockaddr *sa = NULL;
  384. int error = 0;
  385. struct proc *prc = curproc; /* XXX */
  386. s = splnet();
  387. switch(cmd) {
  388. case SIOCSIFADDR:
  389. ifp->if_flags |= IFF_UP;
  390. ifa->ifa_rtrequest = p2p_rtrequest;
  391. break;
  392. case SIOCSIFDSTADDR:
  393. break;
  394. case SIOCSIFFLAGS:
  395. if ((ifr->ifr_flags & IFF_LINK0) != 0)
  396. sc->g_proto = IPPROTO_GRE;
  397. else
  398. sc->g_proto = IPPROTO_MOBILE;
  399. break;
  400. case SIOCSIFMTU:
  401. if (ifr->ifr_mtu < 576) {
  402. error = EINVAL;
  403. break;
  404. }
  405. ifp->if_mtu = ifr->ifr_mtu;
  406. break;
  407. case SIOCGIFMTU:
  408. ifr->ifr_mtu = sc->sc_if.if_mtu;
  409. break;
  410. case SIOCGIFHARDMTU:
  411. ifr->ifr_hardmtu = sc->sc_if.if_hardmtu;
  412. break;
  413. case SIOCADDMULTI:
  414. case SIOCDELMULTI:
  415. break;
  416. case GRESPROTO:
  417. /* Check for superuser */
  418. if ((error = suser(prc, 0)) != 0)
  419. break;
  420. sc->g_proto = ifr->ifr_flags;
  421. switch (sc->g_proto) {
  422. case IPPROTO_GRE:
  423. ifp->if_flags |= IFF_LINK0;
  424. break;
  425. case IPPROTO_MOBILE:
  426. ifp->if_flags &= ~IFF_LINK0;
  427. break;
  428. default:
  429. error = EPROTONOSUPPORT;
  430. break;
  431. }
  432. break;
  433. case GREGPROTO:
  434. ifr->ifr_flags = sc->g_proto;
  435. break;
  436. case GRESADDRS:
  437. case GRESADDRD:
  438. /* Check for superuser */
  439. if ((error = suser(prc, 0)) != 0)
  440. break;
  441. /*
  442. * set tunnel endpoints and mark if as up
  443. */
  444. sa = &ifr->ifr_addr;
  445. if (cmd == GRESADDRS )
  446. sc->g_src = (satosin(sa))->sin_addr;
  447. if (cmd == GRESADDRD )
  448. sc->g_dst = (satosin(sa))->sin_addr;
  449. recompute:
  450. if ((sc->g_src.s_addr != INADDR_ANY) &&
  451. (sc->g_dst.s_addr != INADDR_ANY)) {
  452. if (sc->route.ro_rt != NULL) {
  453. rtfree(sc->route.ro_rt);
  454. sc->route.ro_rt = NULL;
  455. }
  456. /* ip_output() will do the lookup */
  457. bzero(&sc->route, sizeof(sc->route));
  458. ifp->if_flags |= IFF_UP;
  459. }
  460. break;
  461. case GREGADDRS:
  462. bzero(&si, sizeof(si));
  463. si.sin_family = AF_INET;
  464. si.sin_len = sizeof(struct sockaddr_in);
  465. si.sin_addr.s_addr = sc->g_src.s_addr;
  466. sa = sintosa(&si);
  467. ifr->ifr_addr = *sa;
  468. break;
  469. case GREGADDRD:
  470. bzero(&si, sizeof(si));
  471. si.sin_family = AF_INET;
  472. si.sin_len = sizeof(struct sockaddr_in);
  473. si.sin_addr.s_addr = sc->g_dst.s_addr;
  474. sa = sintosa(&si);
  475. ifr->ifr_addr = *sa;
  476. break;
  477. case SIOCSETKALIVE:
  478. if ((error = suser(prc, 0)) != 0)
  479. break;
  480. if (ikar->ikar_timeo < 0 || ikar->ikar_timeo > 86400 ||
  481. ikar->ikar_cnt < 0 || ikar->ikar_cnt > 256) {
  482. error = EINVAL;
  483. break;
  484. }
  485. sc->sc_ka_timout = ikar->ikar_timeo;
  486. sc->sc_ka_cnt = ikar->ikar_cnt;
  487. if (sc->sc_ka_timout == 0 || sc->sc_ka_cnt == 0) {
  488. sc->sc_ka_timout = 0;
  489. sc->sc_ka_cnt = 0;
  490. sc->sc_ka_state = GRE_STATE_UKNWN;
  491. gre_link_state(sc);
  492. break;
  493. }
  494. if (!timeout_pending(&sc->sc_ka_snd)) {
  495. sc->sc_ka_holdmax = sc->sc_ka_cnt;
  496. timeout_add(&sc->sc_ka_snd, 1);
  497. timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timout *
  498. sc->sc_ka_cnt);
  499. }
  500. break;
  501. case SIOCGETKALIVE:
  502. ikar->ikar_timeo = sc->sc_ka_timout;
  503. ikar->ikar_cnt = sc->sc_ka_cnt;
  504. break;
  505. case SIOCSLIFPHYADDR:
  506. if ((error = suser(prc, 0)) != 0)
  507. break;
  508. if (lifr->addr.ss_family != AF_INET ||
  509. lifr->dstaddr.ss_family != AF_INET) {
  510. error = EAFNOSUPPORT;
  511. break;
  512. }
  513. if (lifr->addr.ss_len != sizeof(si) ||
  514. lifr->dstaddr.ss_len != sizeof(si)) {
  515. error = EINVAL;
  516. break;
  517. }
  518. sc->g_src = ((struct sockaddr_in *)&lifr->addr)->sin_addr;
  519. sc->g_dst = ((struct sockaddr_in *)&lifr->dstaddr)->sin_addr;
  520. goto recompute;
  521. case SIOCDIFPHYADDR:
  522. if ((error = suser(prc, 0)) != 0)
  523. break;
  524. sc->g_src.s_addr = INADDR_ANY;
  525. sc->g_dst.s_addr = INADDR_ANY;
  526. break;
  527. case SIOCGLIFPHYADDR:
  528. if (sc->g_src.s_addr == INADDR_ANY ||
  529. sc->g_dst.s_addr == INADDR_ANY) {
  530. error = EADDRNOTAVAIL;
  531. break;
  532. }
  533. bzero(&si, sizeof(si));
  534. si.sin_family = AF_INET;
  535. si.sin_len = sizeof(struct sockaddr_in);
  536. si.sin_addr.s_addr = sc->g_src.s_addr;
  537. memcpy(&lifr->addr, &si, sizeof(si));
  538. si.sin_addr.s_addr = sc->g_dst.s_addr;
  539. memcpy(&lifr->dstaddr, &si, sizeof(si));
  540. break;
  541. case SIOCSLIFPHYRTABLE:
  542. if ((error = suser(prc, 0)) != 0)
  543. break;
  544. if (ifr->ifr_rdomainid < 0 ||
  545. ifr->ifr_rdomainid > RT_TABLEID_MAX ||
  546. !rtable_exists(ifr->ifr_rdomainid)) {
  547. error = EINVAL;
  548. break;
  549. }
  550. sc->g_rtableid = ifr->ifr_rdomainid;
  551. goto recompute;
  552. case SIOCGLIFPHYRTABLE:
  553. ifr->ifr_rdomainid = sc->g_rtableid;
  554. break;
  555. default:
  556. error = ENOTTY;
  557. }
  558. splx(s);
  559. return (error);
  560. }
  561. /*
  562. * do a checksum of a buffer - much like in_cksum, which operates on
  563. * mbufs.
  564. */
  565. u_int16_t
  566. gre_in_cksum(u_int16_t *p, u_int len)
  567. {
  568. u_int32_t sum = 0;
  569. int nwords = len >> 1;
  570. while (nwords-- != 0)
  571. sum += *p++;
  572. if (len & 1) {
  573. union {
  574. u_short w;
  575. u_char c[2];
  576. } u;
  577. u.c[0] = *(u_char *) p;
  578. u.c[1] = 0;
  579. sum += u.w;
  580. }
  581. /* end-around-carry */
  582. sum = (sum >> 16) + (sum & 0xffff);
  583. sum += (sum >> 16);
  584. return (~sum);
  585. }
  586. void
  587. gre_keepalive(void *arg)
  588. {
  589. struct gre_softc *sc = arg;
  590. if (!sc->sc_ka_timout)
  591. return;
  592. sc->sc_ka_state = GRE_STATE_DOWN;
  593. gre_link_state(sc);
  594. }
  595. void
  596. gre_send_keepalive(void *arg)
  597. {
  598. struct gre_softc *sc = arg;
  599. struct mbuf *m;
  600. struct ip *ip;
  601. struct gre_h *gh;
  602. struct sockaddr dst;
  603. int s;
  604. if (sc->sc_ka_timout)
  605. timeout_add_sec(&sc->sc_ka_snd, sc->sc_ka_timout);
  606. if (sc->g_proto != IPPROTO_GRE)
  607. return;
  608. if ((sc->sc_if.if_flags & IFF_UP) == 0 ||
  609. sc->g_src.s_addr == INADDR_ANY || sc->g_dst.s_addr == INADDR_ANY)
  610. return;
  611. MGETHDR(m, M_DONTWAIT, MT_DATA);
  612. if (m == NULL) {
  613. sc->sc_if.if_oerrors++;
  614. return;
  615. }
  616. m->m_len = m->m_pkthdr.len = sizeof(*ip) + sizeof(*gh);
  617. MH_ALIGN(m, m->m_len);
  618. /* build the ip header */
  619. ip = mtod(m, struct ip *);
  620. ip->ip_v = IPVERSION;
  621. ip->ip_hl = sizeof(*ip) >> 2;
  622. ip->ip_tos = IPTOS_LOWDELAY;
  623. ip->ip_len = htons(m->m_pkthdr.len);
  624. ip->ip_id = htons(ip_randomid());
  625. ip->ip_off = htons(IP_DF);
  626. ip->ip_ttl = ip_defttl;
  627. ip->ip_p = IPPROTO_GRE;
  628. ip->ip_src.s_addr = sc->g_dst.s_addr;
  629. ip->ip_dst.s_addr = sc->g_src.s_addr;
  630. ip->ip_sum = 0;
  631. ip->ip_sum = in_cksum(m, sizeof(*ip));
  632. gh = (struct gre_h *)(ip + 1);
  633. /* We don't support any GRE flags for now */
  634. bzero(gh, sizeof(*gh));
  635. bzero(&dst, sizeof(dst));
  636. dst.sa_family = AF_INET;
  637. s = splsoftnet();
  638. /* should we care about the error? */
  639. gre_output(&sc->sc_if, m, &dst, NULL);
  640. splx(s);
  641. }
  642. void
  643. gre_recv_keepalive(struct gre_softc *sc)
  644. {
  645. if (!sc->sc_ka_timout)
  646. return;
  647. /* link state flap dampening */
  648. switch (sc->sc_ka_state) {
  649. case GRE_STATE_UKNWN:
  650. case GRE_STATE_DOWN:
  651. sc->sc_ka_state = GRE_STATE_HOLD;
  652. sc->sc_ka_holdcnt = sc->sc_ka_holdmax;
  653. sc->sc_ka_holdmax = MIN(sc->sc_ka_holdmax * 2,
  654. 16 * sc->sc_ka_cnt);
  655. break;
  656. case GRE_STATE_HOLD:
  657. if (--sc->sc_ka_holdcnt < 1) {
  658. sc->sc_ka_state = GRE_STATE_UP;
  659. gre_link_state(sc);
  660. }
  661. break;
  662. case GRE_STATE_UP:
  663. sc->sc_ka_holdmax--;
  664. sc->sc_ka_holdmax = MAX(sc->sc_ka_holdmax, sc->sc_ka_cnt);
  665. break;
  666. }
  667. /* rescedule hold timer */
  668. timeout_add_sec(&sc->sc_ka_hold, sc->sc_ka_timout * sc->sc_ka_cnt);
  669. }
  670. void
  671. gre_link_state(struct gre_softc *sc)
  672. {
  673. struct ifnet *ifp = &sc->sc_if;
  674. int link_state = LINK_STATE_UNKNOWN;
  675. if (sc->sc_ka_state == GRE_STATE_UP)
  676. link_state = LINK_STATE_UP;
  677. else if (sc->sc_ka_state != GRE_STATE_UKNWN)
  678. link_state = LINK_STATE_KALIVE_DOWN;
  679. if (ifp->if_link_state != link_state) {
  680. ifp->if_link_state = link_state;
  681. if_link_state_change(ifp);
  682. }
  683. }
  684. #endif