Annotation of embedaddon/quagga/ospf6d/ospf6_network.c, revision 1.1.1.3
1.1 misho 1: /*
2: * Copyright (C) 2003 Yasuhiro Ohara
3: *
4: * This file is part of GNU Zebra.
5: *
6: * GNU Zebra is free software; you can redistribute it and/or modify it
7: * under the terms of the GNU General Public License as published by the
8: * Free Software Foundation; either version 2, or (at your option) any
9: * later version.
10: *
11: * GNU Zebra is distributed in the hope that it will be useful, but
12: * WITHOUT ANY WARRANTY; without even the implied warranty of
13: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14: * General Public License for more details.
15: *
16: * You should have received a copy of the GNU General Public License
17: * along with GNU Zebra; see the file COPYING. If not, write to the
18: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19: * Boston, MA 02111-1307, USA.
20: */
21:
22: #include <zebra.h>
23:
24: #include "log.h"
25: #include "memory.h"
26: #include "sockunion.h"
27: #include "sockopt.h"
28: #include "privs.h"
29:
1.1.1.3 ! misho 30: #include "libospf.h"
1.1 misho 31: #include "ospf6_proto.h"
32: #include "ospf6_network.h"
33:
34: extern struct zebra_privs_t ospf6d_privs;
35:
36: int ospf6_sock;
37: struct in6_addr allspfrouters6;
38: struct in6_addr alldrouters6;
39:
40: /* setsockopt MulticastLoop to off */
1.1.1.3 ! misho 41: static void
1.1 misho 42: ospf6_reset_mcastloop (void)
43: {
44: u_int off = 0;
45: if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
46: &off, sizeof (u_int)) < 0)
47: zlog_warn ("Network: reset IPV6_MULTICAST_LOOP failed: %s",
48: safe_strerror (errno));
49: }
50:
1.1.1.3 ! misho 51: static void
1.1 misho 52: ospf6_set_pktinfo (void)
53: {
54: setsockopt_ipv6_pktinfo (ospf6_sock, 1);
55: }
56:
1.1.1.3 ! misho 57: static void
1.1.1.2 misho 58: ospf6_set_transport_class (void)
59: {
60: #ifdef IPTOS_PREC_INTERNETCONTROL
61: setsockopt_ipv6_tclass (ospf6_sock, IPTOS_PREC_INTERNETCONTROL);
62: #endif
63: }
64:
1.1.1.3 ! misho 65: static void
1.1 misho 66: ospf6_set_checksum (void)
67: {
68: int offset = 12;
69: #ifndef DISABLE_IPV6_CHECKSUM
70: if (setsockopt (ospf6_sock, IPPROTO_IPV6, IPV6_CHECKSUM,
71: &offset, sizeof (offset)) < 0)
72: zlog_warn ("Network: set IPV6_CHECKSUM failed: %s", safe_strerror (errno));
73: #else
74: zlog_warn ("Network: Don't set IPV6_CHECKSUM");
75: #endif /* DISABLE_IPV6_CHECKSUM */
76: }
77:
78: /* Make ospf6d's server socket. */
79: int
80: ospf6_serv_sock (void)
81: {
82: if (ospf6d_privs.change (ZPRIVS_RAISE))
83: zlog_err ("ospf6_serv_sock: could not raise privs");
84:
85: ospf6_sock = socket (AF_INET6, SOCK_RAW, IPPROTO_OSPFIGP);
86: if (ospf6_sock < 0)
87: {
88: zlog_warn ("Network: can't create OSPF6 socket.");
89: if (ospf6d_privs.change (ZPRIVS_LOWER))
90: zlog_err ("ospf_sock_init: could not lower privs");
91: return -1;
92: }
93: if (ospf6d_privs.change (ZPRIVS_LOWER))
94: zlog_err ("ospf_sock_init: could not lower privs");
95:
96: /* set socket options */
97: #if 1
98: sockopt_reuseaddr (ospf6_sock);
99: #else
100: ospf6_set_reuseaddr ();
101: #endif /*1*/
102: ospf6_reset_mcastloop ();
103: ospf6_set_pktinfo ();
1.1.1.2 misho 104: ospf6_set_transport_class ();
1.1 misho 105: ospf6_set_checksum ();
106:
107: /* setup global in6_addr, allspf6 and alldr6 for later use */
108: inet_pton (AF_INET6, ALLSPFROUTERS6, &allspfrouters6);
109: inet_pton (AF_INET6, ALLDROUTERS6, &alldrouters6);
110:
111: return 0;
112: }
113:
1.1.1.2 misho 114: /* ospf6 set socket option */
1.1 misho 115: void
1.1.1.3 ! misho 116: ospf6_sso (ifindex_t ifindex, struct in6_addr *group, int option)
1.1 misho 117: {
118: struct ipv6_mreq mreq6;
1.1.1.2 misho 119: int ret;
1.1 misho 120:
121: assert (ifindex);
122: mreq6.ipv6mr_interface = ifindex;
1.1.1.2 misho 123: memcpy (&mreq6.ipv6mr_multiaddr, group, sizeof (struct in6_addr));
1.1 misho 124:
1.1.1.2 misho 125: ret = setsockopt (ospf6_sock, IPPROTO_IPV6, option,
126: &mreq6, sizeof (mreq6));
127: if (ret < 0)
128: zlog_err ("Network: setsockopt (%d) on ifindex %d failed: %s",
129: option, ifindex, safe_strerror (errno));
1.1 misho 130: }
131:
132: static int
133: iov_count (struct iovec *iov)
134: {
135: int i;
136: for (i = 0; iov[i].iov_base; i++)
137: ;
138: return i;
139: }
140:
141: static int
142: iov_totallen (struct iovec *iov)
143: {
144: int i;
145: int totallen = 0;
146: for (i = 0; iov[i].iov_base; i++)
147: totallen += iov[i].iov_len;
148: return totallen;
149: }
150:
151: int
152: ospf6_sendmsg (struct in6_addr *src, struct in6_addr *dst,
1.1.1.3 ! misho 153: ifindex_t *ifindex, struct iovec *message)
1.1 misho 154: {
155: int retval;
156: struct msghdr smsghdr;
157: struct cmsghdr *scmsgp;
158: u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
159: struct in6_pktinfo *pktinfo;
160: struct sockaddr_in6 dst_sin6;
161:
162: assert (dst);
163: assert (*ifindex);
164:
165: scmsgp = (struct cmsghdr *)cmsgbuf;
166: pktinfo = (struct in6_pktinfo *)(CMSG_DATA(scmsgp));
167: memset (&dst_sin6, 0, sizeof (struct sockaddr_in6));
168:
169: /* source address */
170: pktinfo->ipi6_ifindex = *ifindex;
171: if (src)
172: memcpy (&pktinfo->ipi6_addr, src, sizeof (struct in6_addr));
173: else
174: memset (&pktinfo->ipi6_addr, 0, sizeof (struct in6_addr));
175:
176: /* destination address */
177: dst_sin6.sin6_family = AF_INET6;
178: #ifdef SIN6_LEN
179: dst_sin6.sin6_len = sizeof (struct sockaddr_in6);
180: #endif /*SIN6_LEN*/
181: memcpy (&dst_sin6.sin6_addr, dst, sizeof (struct in6_addr));
182: #ifdef HAVE_SIN6_SCOPE_ID
183: dst_sin6.sin6_scope_id = *ifindex;
184: #endif
185:
186: /* send control msg */
187: scmsgp->cmsg_level = IPPROTO_IPV6;
188: scmsgp->cmsg_type = IPV6_PKTINFO;
189: scmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
190: /* scmsgp = CMSG_NXTHDR (&smsghdr, scmsgp); */
191:
192: /* send msg hdr */
193: memset (&smsghdr, 0, sizeof (smsghdr));
194: smsghdr.msg_iov = message;
195: smsghdr.msg_iovlen = iov_count (message);
196: smsghdr.msg_name = (caddr_t) &dst_sin6;
197: smsghdr.msg_namelen = sizeof (struct sockaddr_in6);
198: smsghdr.msg_control = (caddr_t) cmsgbuf;
1.1.1.3 ! misho 199: smsghdr.msg_controllen = scmsgp->cmsg_len;
1.1 misho 200:
201: retval = sendmsg (ospf6_sock, &smsghdr, 0);
202: if (retval != iov_totallen (message))
203: zlog_warn ("sendmsg failed: ifindex: %d: %s (%d)",
204: *ifindex, safe_strerror (errno), errno);
205:
206: return retval;
207: }
208:
209: int
210: ospf6_recvmsg (struct in6_addr *src, struct in6_addr *dst,
1.1.1.3 ! misho 211: ifindex_t *ifindex, struct iovec *message)
1.1 misho 212: {
213: int retval;
214: struct msghdr rmsghdr;
215: struct cmsghdr *rcmsgp;
216: u_char cmsgbuf[CMSG_SPACE(sizeof (struct in6_pktinfo))];
217: struct in6_pktinfo *pktinfo;
218: struct sockaddr_in6 src_sin6;
219:
220: rcmsgp = (struct cmsghdr *)cmsgbuf;
221: pktinfo = (struct in6_pktinfo *)(CMSG_DATA(rcmsgp));
222: memset (&src_sin6, 0, sizeof (struct sockaddr_in6));
223:
224: /* receive control msg */
225: rcmsgp->cmsg_level = IPPROTO_IPV6;
226: rcmsgp->cmsg_type = IPV6_PKTINFO;
227: rcmsgp->cmsg_len = CMSG_LEN (sizeof (struct in6_pktinfo));
228: /* rcmsgp = CMSG_NXTHDR (&rmsghdr, rcmsgp); */
229:
230: /* receive msg hdr */
231: memset (&rmsghdr, 0, sizeof (rmsghdr));
232: rmsghdr.msg_iov = message;
233: rmsghdr.msg_iovlen = iov_count (message);
234: rmsghdr.msg_name = (caddr_t) &src_sin6;
235: rmsghdr.msg_namelen = sizeof (struct sockaddr_in6);
236: rmsghdr.msg_control = (caddr_t) cmsgbuf;
237: rmsghdr.msg_controllen = sizeof (cmsgbuf);
238:
239: retval = recvmsg (ospf6_sock, &rmsghdr, 0);
240: if (retval < 0)
241: zlog_warn ("recvmsg failed: %s", safe_strerror (errno));
242: else if (retval == iov_totallen (message))
243: zlog_warn ("recvmsg read full buffer size: %d", retval);
244:
245: /* source address */
246: assert (src);
247: memcpy (src, &src_sin6.sin6_addr, sizeof (struct in6_addr));
248:
249: /* destination address */
250: if (ifindex)
251: *ifindex = pktinfo->ipi6_ifindex;
252: if (dst)
253: memcpy (dst, &pktinfo->ipi6_addr, sizeof (struct in6_addr));
254:
255: return retval;
256: }
257:
258:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>