Annotation of embedaddon/pimdd/routesock.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (c) 1998 by the University of Southern California.
3: * All rights reserved.
4: *
5: * Permission to use, copy, modify, and distribute this software and
6: * its documentation in source and binary forms for lawful
7: * purposes and without fee is hereby granted, provided
8: * that the above copyright notice appear in all copies and that both
9: * the copyright notice and this permission notice appear in supporting
10: * documentation, and that any documentation, advertising materials,
11: * and other materials related to such distribution and use acknowledge
12: * that the software was developed by the University of Southern
13: * California and/or Information Sciences Institute.
14: * The name of the University of Southern California may not
15: * be used to endorse or promote products derived from this software
16: * without specific prior written permission.
17: *
18: * THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY REPRESENTATIONS
19: * ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY PURPOSE. THIS SOFTWARE IS
20: * PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
21: * INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
22: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
23: * NON-INFRINGEMENT.
24: *
25: * IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
26: * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT,
27: * TORT, OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH,
28: * THE USE OR PERFORMANCE OF THIS SOFTWARE.
29: *
30: * Other copyrights might apply to parts of this software and are so
31: * noted when applicable.
32: */
33: /*
34: * Questions concerning this software should be directed to
35: * Pavlin Ivanov Radoslavov (pavlin@catarina.usc.edu)
36: *
37: * $Id: routesock.c,v 1.2 1998/05/29 20:08:57 kurtw Exp $
38: */
39: /*
40: * Part of this program has been derived from mrouted.
41: * The mrouted program is covered by the license in the accompanying file
42: * named "LICENSE.mrouted".
43: *
44: * The mrouted program is COPYRIGHT 1989 by The Board of Trustees of
45: * Leland Stanford Junior University.
46: *
47: */
48:
49: #include <sys/param.h>
50: #include <sys/file.h>
51: #include "defs.h"
52: #include <sys/socket.h>
53: #include <net/route.h>
54: #ifdef HAVE_ROUTING_SOCKETS
55: #include <net/if_dl.h>
56: #endif
57: #include <arpa/inet.h>
58: #include <netdb.h>
59: #include <stdlib.h>
60:
61: #ifdef HAVE_ROUTING_SOCKETS
62: union sockunion {
63: struct sockaddr sa;
64: struct sockaddr_in sin;
65: struct sockaddr_dl sdl;
66: } so_dst, so_ifp;
67: typedef union sockunion *sup;
68: int routing_socket;
69: int rtm_addrs, pid;
70: struct rt_metrics rt_metrics;
71: u_long rtm_inits;
72:
73: /*
74: * Local functions definitions.
75: */
76: static int getmsg __P((register struct rt_msghdr *, int,
77: struct rpfctl *rpfinfo));
78:
79: /*
80: * TODO: check again!
81: */
82: #ifdef IRIX
83: #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(__uint64_t) - 1))) \
84: : sizeof(__uint64_t))
85: #else
86: #define ROUNDUP(a) ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) \
87: : sizeof(long))
88: #endif /* IRIX */
89:
90: #ifdef HAVE_SA_LEN
91: #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
92: #else
93: #define ADVANCE(x, n) (x += ROUNDUP(4)) /* TODO: a hack!! */
94: #endif
95:
96: /* Open and initialize the routing socket */
97: int
98: init_routesock()
99: {
100: int off;
101:
102: pid = getpid();
103: routing_socket = socket(PF_ROUTE, SOCK_RAW, 0);
104: if (routing_socket < 0) {
105: log(LOG_ERR, 0, "\nRouting socket error");
106: return -1;
107: }
108: if (fcntl(routing_socket, F_SETFL, O_NONBLOCK) == -1){
109: log(LOG_ERR, 0, "\n Routing socket error");
110: return -1;
111: }
112: if (setsockopt(routing_socket, SOL_SOCKET,
113: SO_USELOOPBACK, (char *)&off,
114: sizeof(off)) < 0){
115: log(LOG_ERR, 0 , "\n setsockopt(SO_USELOOPBACK,0)");
116: return -1;
117: }
118: return 0;
119: }
120:
121:
122: struct {
123: struct rt_msghdr m_rtm;
124: char m_space[512];
125: } m_rtmsg;
126:
127:
128: /* get the rpf neighbor info */
129: int
130: k_req_incoming(source, rpfp)
131: u_int32 source;
132: struct rpfctl *rpfp;
133: {
134: int flags = RTF_STATIC;
135: register sup su;
136: static int seq;
137: int rlen;
138: register char *cp = m_rtmsg.m_space;
139: register int l;
140: struct rpfctl rpfinfo;
141:
142: /* TODO: a hack!!!! */
143: #ifdef HAVE_SA_LEN
144: #define NEXTADDR(w, u) \
145: if (rtm_addrs & (w)) { \
146: l = ROUNDUP(u.sa.sa_len); bcopy((char *)&(u), cp, l); cp += l;\
147: }
148: #else
149: #define NEXTADDR(w, u) \
150: if (rtm_addrs & (w)) { \
151: l = ROUNDUP(4); bcopy((char *)&(u), cp, l); cp += l;\
152: }
153: #endif /* HAVE_SA_LEN */
154:
155: /* initialize */
156: rpfp->rpfneighbor.s_addr = INADDR_ANY_N;
157: rpfp->source.s_addr = source;
158:
159: /* check if local address or directly connected before calling the
160: * routing socket
161: */
162: if ((rpfp->iif = find_vif_direct_local(source)) != NO_VIF) {
163: rpfp->rpfneighbor.s_addr = source;
164: return(TRUE);
165: }
166:
167: /* prepare the routing socket params */
168: rtm_addrs |= RTA_DST;
169: rtm_addrs |= RTA_IFP;
170: su = &so_dst;
171: su->sin.sin_family = AF_INET;
172: #ifdef HAVE_SA_LEN
173: su->sin.sin_len = sizeof(struct sockaddr_in);
174: #endif
175: su->sin.sin_addr.s_addr = source;
176: if (inet_lnaof(su->sin.sin_addr) == INADDR_ANY) {
177: IF_DEBUG(DEBUG_RPF)
178: log(LOG_DEBUG, 0, "k_req_incoming: Invalid source %s",
179: inet_fmt(source,s1));
180: return(FALSE);
181: }
182: so_ifp.sa.sa_family = AF_LINK;
183: #ifdef HAVE_SA_LEN
184: so_ifp.sa.sa_len = sizeof(struct sockaddr_dl);
185: #endif
186: flags |= RTF_UP;
187: flags |= RTF_HOST;
188: flags |= RTF_GATEWAY;
189: errno = 0;
190: bzero((char *)&m_rtmsg, sizeof(m_rtmsg));
191:
192: #define rtm m_rtmsg.m_rtm
193: rtm.rtm_type = RTM_GET;
194: rtm.rtm_flags = flags;
195: rtm.rtm_version = RTM_VERSION;
196: rtm.rtm_seq = ++seq;
197: rtm.rtm_addrs = rtm_addrs;
198: rtm.rtm_rmx = rt_metrics;
199: rtm.rtm_inits = rtm_inits;
200:
201: NEXTADDR(RTA_DST, so_dst);
202: NEXTADDR(RTA_IFP, so_ifp);
203: rtm.rtm_msglen = l = cp - (char *)&m_rtmsg;
204:
205: if ((rlen = write(routing_socket, (char *)&m_rtmsg, l)) < 0) {
206: IF_DEBUG(DEBUG_RPF | DEBUG_KERN) {
207: if (errno == ESRCH)
208: log(LOG_DEBUG, 0,
209: "Writing to routing socket: no such route\n");
210: else
211: log(LOG_DEBUG, 0, "Error writing to routing socket");
212: }
213: return(FALSE);
214: }
215:
216: do {
217: l = read(routing_socket, (char *)&m_rtmsg, sizeof(m_rtmsg));
218: } while (l > 0 && (rtm.rtm_seq != seq || rtm.rtm_pid != pid));
219:
220: if (l < 0) {
221: IF_DEBUG(DEBUG_RPF | DEBUG_KERN)
222: log(LOG_DEBUG, 0, "Read from routing socket failed");
223: return(FALSE);
224: }
225:
226: if (getmsg(&rtm, l, &rpfinfo)){
227: rpfp->rpfneighbor.s_addr = rpfinfo.rpfneighbor.s_addr;
228: rpfp->iif = rpfinfo.iif;
229: }
230: #undef rtm
231: return (TRUE);
232: }
233:
234:
235: /*
236: * Returns TRUE on success, FALSE otherwise. rpfinfo contains the result.
237: */
238: int
239: getmsg(rtm, msglen, rpfinfop)
240: register struct rt_msghdr *rtm;
241: int msglen;
242: struct rpfctl *rpfinfop;
243: {
244: struct sockaddr *dst = NULL, *gate = NULL, *mask = NULL;
245: struct sockaddr_dl *ifp = NULL;
246: register struct sockaddr *sa;
247: register char *cp;
248: register int i;
249: struct in_addr in;
250: vifi_t vifi;
251: struct uvif *v;
252:
253: if (rpfinfop == (struct rpfctl *)NULL)
254: return(FALSE);
255:
256: in = ((struct sockaddr_in *)&so_dst)->sin_addr;
257: IF_DEBUG(DEBUG_RPF)
258: log(LOG_DEBUG, 0, "route to: %s", inet_fmt(in.s_addr, s1));
259: cp = ((char *)(rtm + 1));
260: if (rtm->rtm_addrs)
261: for (i = 1; i; i <<= 1)
262: if (i & rtm->rtm_addrs) {
263: sa = (struct sockaddr *)cp;
264: switch (i) {
265: case RTA_DST:
266: dst = sa;
267: break;
268: case RTA_GATEWAY:
269: gate = sa;
270: break;
271: case RTA_NETMASK:
272: mask = sa;
273: break;
274: case RTA_IFP:
275: if (sa->sa_family == AF_LINK &&
276: ((struct sockaddr_dl *)sa)->sdl_nlen)
277: ifp = (struct sockaddr_dl *)sa;
278: break;
279: }
280: ADVANCE(cp, sa);
281: }
282:
283: if (!ifp){ /* No incoming interface */
284: IF_DEBUG(DEBUG_RPF)
285: log(LOG_DEBUG, 0,
286: "No incoming interface for destination %s",
287: inet_fmt(in.s_addr, s1));
288: return(FALSE);
289: }
290: if (dst && mask)
291: mask->sa_family = dst->sa_family;
292: if (dst) {
293: in = ((struct sockaddr_in *)dst)->sin_addr;
294: IF_DEBUG(DEBUG_RPF)
295: log(LOG_DEBUG, 0, " destination is: %s",
296: inet_fmt(in.s_addr, s1));
297: }
298: if (gate && rtm->rtm_flags & RTF_GATEWAY) {
299: in = ((struct sockaddr_in *)gate)->sin_addr;
300: IF_DEBUG(DEBUG_RPF)
301: log(LOG_DEBUG, 0, " gateway is: %s",
302: inet_fmt(in.s_addr, s1));
303: rpfinfop->rpfneighbor = in;
304: }
305:
306: for (vifi = 0, v = uvifs; vifi < numvifs; ++vifi, ++v)
307: /* get the number of the interface by matching the name */
308: if (!(strncmp(v->uv_name,ifp->sdl_data,ifp->sdl_nlen)))
309: break;
310:
311: IF_DEBUG(DEBUG_RPF)
312: log(LOG_DEBUG, 0, " iif is %d", vifi);
313:
314: rpfinfop->iif = vifi;
315:
316: if (vifi >= numvifs){
317: IF_DEBUG(DEBUG_RPF)
318: log(LOG_DEBUG, 0, "Invalid incoming interface for destination %s, because of invalid virtual interface", inet_fmt(in.s_addr, s1));
319: return(FALSE);/* invalid iif */
320: }
321:
322: return(TRUE);
323: }
324:
325:
326: #else /* HAVE_ROUTING_SOCKETS */
327:
328:
329: /*
330: * Return in rpfcinfo the incoming interface and the next hop router
331: * toward source.
332: */
333: /* TODO: check whether next hop router address is in network or host order */
334: int
335: k_req_incoming(source, rpfcinfo)
336: u_int32 source;
337: struct rpfctl *rpfcinfo;
338: {
339: rpfcinfo->source.s_addr = source;
340: rpfcinfo->iif = NO_VIF; /* just initialized, will be */
341: /* changed in kernel */
342: rpfcinfo->rpfneighbor.s_addr = INADDR_ANY; /* initialized */
343:
344: if (ioctl(udp_socket, SIOCGETRPF, (char *) rpfcinfo) < 0){
345: log(LOG_ERR, errno, "ioctl SIOCGETRPF k_req_incoming");
346: return(FALSE);
347: }
348: return (TRUE);
349: }
350: #endif /* HAVE_ROUTING_SOCKETS */
351:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>