|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1996 Apple Computer, Inc.
27: *
28: * The information contained herein is subject to change without
29: * notice and should not be construed as a commitment by Apple
30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility
31: * for any errors that may appear.
32: *
33: * Confidential and Proprietary to Apple Computer, Inc.
34: *
35: * File: aurpd.c
36: */
37:
38: /*
39: * Kernel process to implement the AURP daemon:
40: * manage tunnels to remote AURP servers across IP networks
41: */
42: #ifdef _AIX
43: #include <sys/sleep.h>
44: #endif
45: #include <sysglue.h>
46: #ifdef _AIX
47: #include <sys/atomic_op.h>
48: #endif
49: #include <sys/socket.h>
50: #include <sys/socketvar.h>
51: #include <sys/protosw.h>
52: #include <sys/errno.h>
53: #include <netinet/in.h>
54: #include <at/appletalk.h>
55: #include <lap.h>
56: #include <routing_tables.h>
57: #define _AURP
58: #define _KERNSYS
59: #include <at/aurp.h>
60: #include <at_aurp.h>
61:
62:
63: #undef e_sleep_thread
64: #define M_RCVBUF (64 * 1024)
65: #define M_SNDBUF (64 * 1024)
66: struct aurp_global_t aurp_global;
67: /*
68: * Initialize the aurp pipe -
69: * -Create, initialize, and start the aurpd kernel process; we need
70: * a process to permit queueing between the socket and the stream,
71: * which is necessary for orderly access to the socket structure.
72: * -The user process (aurpd) is there to 'build' the AURP
73: * stream, act as a 'logging agent' (:-}), and hold open the stream
74: * during its use.
75: * -Data and AURP packets from the DDP stream will be fed into the
76: * UDP tunnel (AURPsend())
77: * -Data and AURP packets from the UDP tunnel will be fed into the
78: * DDP stream (ip_to_atalk(), via the kernel process).
79: */
80: aurpd_start()
81: { register int error;
82: register struct socket *so;
83: int maxbuf;
84: extern void aurp_wakeup(caddr_t, int);
85: /****### TEMPO HACK 9/26: we need more args than that for suser in bsd4.4
86: if (!suser())
87: return(EPERM);
88: */
89:
90: /*
91: * Set up state prior to starting kernel process so we can back out
92: * (error return) if something goes wrong.
93: */
94: bzero((char *)&aurp_global.tunnel, sizeof(aurp_global.tunnel));
95: /*lock_alloc(&aurp_global.glock, LOCK_ALLOC_PIN, AURP_EVNT_LOCK, -1);*/
96: ATLOCKINIT(aurp_global.glock);
97: ATEVENTINIT(aurp_global.event_anchor);
98:
99: /* open udp socket */
100: if (aurp_global.udp_port == 0)
101: aurp_global.udp_port = AURP_SOCKNUM;
102: error = socreate(AF_INET, &aurp_global.tunnel, SOCK_DGRAM,
103: IPPROTO_UDP);
104: if (error)
105: { dPrintf(D_M_AURP, D_L_FATAL, ("AURP: Can't get socket (%d)\n",
106: error));
107: return(error);
108: }
109:
110: so = aurp_global.tunnel;
111:
112: if (error = aurp_bindrp(so))
113: { dPrintf(D_M_AURP, D_L_FATAL,
114: ("AURP: Can't bind to port %d (%d)\n",
115: &aurp_global.udp_port, error));
116: soclose(so);
117: return(error);
118: }
119:
120: #ifdef _AIX
121: SOCKET_LOCK(so);
122: #else
123: sblock(&so->so_rcv, M_WAIT);
124: sblock(&so->so_snd, M_WAIT);
125: #endif
126: maxbuf = M_RCVBUF;
127: setsockopt(so,SOL_SOCKET,SO_RCVBUF,&maxbuf,sizeof(maxbuf));
128: maxbuf = M_SNDBUF;
129: setsockopt(so,SOL_SOCKET,SO_SNDBUF,&maxbuf,sizeof(maxbuf));
130: #ifdef _AIX
131: so->so_snd.sb_wakeup = 0;
132: so->so_snd.sb_wakearg = 0;
133: so->so_rcv.sb_wakeup = aurp_wakeup;
134: so->so_rcv.sb_wakearg = (caddr_t)AE_UDPIP; /* Yuck */
135: so->so_rcv.sb_iodone = 0;
136: so->so_rcv.sb_ioarg = 0;
137: #else
138: so->so_upcall = aurp_wakeup;
139: so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */
140: #endif
141:
142: so->so_state |= SS_NBIO;
143: #ifdef _AIX
144: so->so_special |=(SP_NOUAREA|SP_EXTPRIV);
145: #else
146: kprintf("aurpd: warning what do we do with so_special?");
147: #endif
148: so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR);
149: so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR);
150: #ifdef _AIX
151: SOCKET_UNLOCK(so);
152: #else
153: sbunlock(&so->so_snd);
154: sbunlock(&so->so_rcv);
155: #endif
156:
157: return(0);
158: }
159:
160: AURPgetmsg(err)
161: int *err;
162: { register struct socket *so;
163: register int s, events;
164:
165: so = aurp_global.tunnel;
166:
167: for (;;)
168: { gbuf_t *from, *p_mbuf;
169: #ifdef _AIX
170: int flags = MSG_NONBLOCK;
171: #else
172: int flags = MSG_DONTWAIT;
173: #endif
174: struct uio auio;
175:
176: /*
177: * Wait for a package to arrive. This will be from the
178: * IP side - sowakeup() calls aurp_wakeup()
179: * when a packet arrives
180: */
181:
182: ATDISABLE(s, aurp_global.glock);
183: events = aurp_global.event;
184: if (events == 0)
185: {
186: #ifdef _AIX
187: e_sleep_thread(&aurp_global.event_anchor,
188: &aurp_global.glock, LOCK_HANDLER);
189: #else
190: (void) tsleep(&aurp_global.event_anchor, PSOCK, "AURPgetmsg", 0);
191: #endif
192: events = aurp_global.event;
193: aurp_global.event = 0;
194: }
195: ATENABLE(s, aurp_global.glock);
196:
197: if (events & AE_SHUTDOWN)
198: {
199: aurp_global.shutdown = 1;
200: while (aurp_global.running)
201: ;
202: /*lock_free(&aurp_global.glock);*/
203: aurp_global.tunnel = 0;
204: aurp_global.event = 0;
205: soclose(so);
206: *err = ESHUTDOWN;
207: return -1;
208: }
209:
210:
211:
212: /*
213: * Set up the nominal uio structure -
214: * give it no iov's, point off to non-existant user space,
215: * but make sure the 'resid' count means somehting.
216: */
217:
218: auio.uio_iov = NULL;
219: auio.uio_iovcnt = 0;
220: auio.uio_segflg = UIO_SYSSPACE;
221: auio.uio_offset = 0; /* XXX */
222:
223: /* Keep up an even flow... */
224: for (;;)
225: { register int empty = 0;
226:
227: /*
228: * This should be large enough to encompass a full DDP packet plus
229: * domain header.
230: */
231: #define A_LARGE_SIZE 700
232: #ifdef _AIX
233: flags = MSG_NONBLOCK;
234: #else
235: flags = MSG_DONTWAIT;
236: #endif
237: auio.uio_resid = A_LARGE_SIZE;
238: *err = soreceive(so, &from, &auio, &p_mbuf, 0, &flags);
239: dPrintf(D_M_AURP, D_L_WARNING,
240: ("aurpd: soreceive returned %d\n", *err));
241: /* soreceive() sets *mp to zero! at start */
242: if (p_mbuf)
243: ip_to_atalk(from, p_mbuf);
244: else
245: break;
246: }
247: }
248:
249: return -1;
250: }
251:
252: /*
253: * Wakeup the sleeping giant - we've put a message on his queue(s).
254: * The arg indicates what queue has been updated.
255: */
256: void aurp_wakeup(register caddr_t p, int state)
257: { register int s;
258: register int bit;
259:
260: bit = (int) p;
261: ATDISABLE(s, aurp_global.glock);
262: aurp_global.event |= bit;
263: ATENABLE(s, aurp_global.glock);
264: #ifdef _AIX
265: e_wakeup(&aurp_global.event_anchor);
266: #else
267: thread_wakeup(&aurp_global.event_anchor);
268: #endif
269: }
270:
271: /*
272: * Try to bind to the specified reserved port.
273: * Sort of like sobind(), but no suser() check.
274: */
275: aurp_bindrp(so)
276: register struct socket *so;
277: {
278: struct sockaddr_in *sin;
279: gbuf_t *m;
280: u_short i;
281: int error;
282: struct ucred *savecred;
283:
284: m = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in));
285: if (m == NULL) {
286: dPrintf(D_M_AURP, D_L_ERROR,
287: ("aurp_bindrp: couldn't alloc mbuf"));
288: return (ENOBUFS);
289: }
290:
291: sin = (struct sockaddr_in *)gbuf_rptr(m);
292: sin->sin_family = AF_INET;
293: sin->sin_addr.s_addr = htons(aurp_global.src_addr);
294: sin->sin_port = htons(aurp_global.udp_port);
295: gbuf_len(m) = sizeof(struct sockaddr_in);
296:
297: #ifdef _AIX
298: SOCKET_LOCK(so);
299: #else
300: sblock(&so->so_rcv, M_WAIT);
301: sblock(&so->so_snd, M_WAIT);
302: #endif
303: so->so_state |= SS_PRIV;
304: error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, 0, m, 0);
305: #ifdef _AIX
306: SOCKET_UNLOCK(so);
307: #else
308: sbunlock(&so->so_snd);
309: sbunlock(&so->so_rcv);
310: #endif
311:
312: (void) gbuf_freeb(m);
313: return (error);
314: }
315:
316: /*
317: * receive from UDP
318: * fp is the 'source address' mbuf; p_mbuf is the data mbuf.
319: * Use the source address to find the 'node number' (index of the address),
320: * and pass that to the next stage.
321: */
322: int ip_to_atalk(register gbuf_t *fp, register gbuf_t *p_mbuf)
323: { register aurp_hdr_t *hdr;
324: register domain_t *domain;
325: unsigned char node;
326: register struct sockaddr_in *rem_addr;
327:
328: rem_addr = (struct sockaddr_in *)gbuf_rptr(fp);
329: /* determine the node where the packet came from */
330: for (node=1; node <= dst_addr_cnt; node++) {
331: if (aurp_global.dst_addr[node] == *(long *)&rem_addr->sin_addr)
332: break;
333: }
334: if (node > dst_addr_cnt) {
335: dPrintf(D_M_AURP, D_L_WARNING,
336: ("AURPrecv: invalid node, %d.%x\n",
337: rem_addr->sin_port,
338: *(long *)&rem_addr->sin_addr));
339: gbuf_freem(fp);
340: gbuf_freem(p_mbuf);
341: return -1;
342: }
343:
344: /* validate the domain */
345: domain = (domain_t *)gbuf_rptr(p_mbuf);
346: if ( (domain->dst_length != IP_LENGTH) ||
347: (domain->dst_authority != IP_AUTHORITY) ||
348: (domain->version != AUD_Version) ||
349: ((domain->type != AUD_Atalk) && (domain->type != AUD_AURP)) ) {
350: dPrintf(D_M_AURP, D_L_WARNING,
351: ("AURPrecv: invalid domain, %d.%x\n",
352: rem_addr->sin_port,
353: *(long *)&rem_addr->sin_addr));
354: gbuf_freem(fp);
355: gbuf_freem(p_mbuf);
356: return -1;
357: }
358:
359: /* Remove domain header */
360: p_mbuf->m_pkthdr.len -= IP_DOMAINSIZE;
361: gbuf_rinc(p_mbuf,IP_DOMAINSIZE);
362: gbuf_set_type(p_mbuf, MSG_DATA);
363:
364: /* forward the packet to the local AppleTalk stack */
365: gbuf_freem(fp);
366: at_insert(p_mbuf, domain->type, node);
367: return 0;
368: }
369:
370: /*
371: * send to UDP
372: * The real work has been done already. Here, we just cobble together
373: * a sockaddr for the destination and call sosend().
374: */
375: void
376: atalk_to_ip(register gbuf_t *m)
377: { register domain_t *domain;
378: int error;
379: #ifdef _AIX
380: int flags = MSG_NONBLOCK;
381: #else
382: int flags = MSG_DONTWAIT;
383: #endif
384: struct sockaddr_in *rem_addr;
385: register gbuf_t *mbp;
386:
387: m->m_type = MT_HEADER;
388: m->m_pkthdr.len = gbuf_msgsize(m);
389: m->m_pkthdr.rcvif = 0;
390:
391: /* Cons up a destination sockaddr */
392: if ((mbp = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in))) == NULL)
393: {
394: #ifdef _AIX
395: (void)fetch_and_add((atomic_p)&aurp_global.no_mbufs, 1);
396: #endif
397: gbuf_freem(m);
398: return;
399: }
400:
401: rem_addr = (struct sockaddr_in *)gbuf_rptr(mbp);
402: bzero((char *)rem_addr, sizeof(rem_addr));
403: rem_addr->sin_family = PF_INET;
404: rem_addr->sin_port = aurp_global.udp_port;
405: gbuf_len(mbp) = sizeof (struct sockaddr_in);
406: domain = (domain_t *)gbuf_rptr(m);
407: *(long *)&rem_addr->sin_addr = domain->dst_address;
408:
409: #ifdef _AIX
410: (void)fetch_and_add((atomic_p)&aurp_global.running, 1);
411: #endif
412: if (aurp_global.shutdown) {
413: gbuf_freem(m);
414: gbuf_freeb(mbp);
415: #ifdef _AIX
416: (void)fetch_and_add((atomic_p)&aurp_global.running, -1);
417: #endif
418: return;
419: }
420: error = sosend(aurp_global.tunnel, mbp, NULL, m, NULL, flags);
421: if (error)
422: { /*log error*/
423: dPrintf(D_M_AURP, D_L_ERROR, ("AURP: sosend error (%d)\n",
424: error));
425: }
426:
427: gbuf_freeb(mbp);
428: #ifdef _AIX
429: (void)fetch_and_add((atomic_p)&aurp_global.running, -1);
430: #endif
431: return;
432: }
433:
434:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.