home *** CD-ROM | disk | FTP | other *** search
- /*
- c_nit.c
- */
- /* Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
-
- Distributed under the terms of the GNU General Public License
- version 2 of june 1991 as published by the Free Software
- Foundation, Inc.
-
- This file is part of M0.
-
- M0 is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone for
- the consequences of using it or for whether it serves any particular
- purpose or works at all, unless he says so in writing. Refer to the GNU
- General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute M0, but
- only under the conditions described in the GNU General Public License.
- A copy of this license is supposed to have been given to you along with
- M0 so you can know your rights and responsibilities. It should be in a
- file named LICENSE. Among other things, the copyright notice and this
- notice must be preserved on all copies. */
-
- #include "c_proto.h"
-
-
- #ifdef CHANNEL_NIT
-
- /* sun NIT (network interface tap) device for M0 */
-
- #include <stdio.h>
- #include <malloc.h>
-
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <sys/time.h>
- #include <signal.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <errno.h>
-
- #include <stropts.h>
- #include <sys/ioctl.h>
- #include <sys/fcntlcom.h>
-
- #include <net/if.h>
- #include <net/nit_if.h>
- #include <net/nit_pf.h>
- #include <net/packetfilt.h>
- #include <sys/uio.h>
-
-
- struct nit_data {
- eindex chankey;
- sint chan;
- byte dest[6];
- };
-
- #define MAXNITCHANNELS 2
- static int nit_fd[MAXNITCHANNELS];
- static ushort m0_eth_type;
- static byte eth_buf[1450];
-
- eindex nit_addr;
- eindex nit_name;
-
-
- /* ------------------------------------------------------------------------ */
-
-
- char**
- get_eth_devices()
- {
- static char* names[] = {"le0", "le1", "le2", "ie0", "ie1", "ie2", 0};
- return names;
- }
-
-
- int
- nit_init(char **devs, int proto)
- {
- int i, j;
- char **d;
-
- for (d = devs, i = 0; d && *d; d++, i++);
- if (!i)
- return -1;
-
- nit_addr = new_array(0, i);
- nit_name = name_add("ether", 5, A_EXECUTABLE);
- m0_eth_type = htons(proto);
-
- for (d = devs, i = 0, j = 0; d && *d && j < MAXNITCHANNELS; d++, i++) {
- struct ifreq ifr;
- struct packetfilt pf;
- register u_short *fwp = pf.Pf_Filter;
- int fd;
- eindex e;
- byteptr a;
-
- fd = open("/dev/nit", O_RDWR);
- if (fd < 0)
- break;
-
- if (ioctl(fd, I_SRDOPT, (char*)RMSGN) < 0 ||
- ioctl(fd, I_PUSH, "pf") < 0)
- continue;
-
- *fwp++ = ENF_PUSHWORD + 6;
- *fwp++ = ENF_PUSHLIT;
- *fwp++ = m0_eth_type;
- *fwp++ = ENF_EQ;
- pf.Pf_FilterLen = fwp - &pf.Pf_Filter[0];
- if (ioctl(fd, NIOCSETF, (char*)&pf) < 0)
- continue;
-
- strncpy(ifr.ifr_name, *d, sizeof(ifr.ifr_name));
- ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
- if( ioctl(fd, NIOCBIND, (char*)&ifr) ||
- ioctl(fd, NIOCSFLAGS, (char*)0) < 0 ||
- ioctl(fd, I_FLUSH, (char*)FLUSHR) < 0 ||
- ioctl(fd, SIOCGIFADDR, (char*)&ifr) < 0)
- continue;
-
- nit_fd[j] = fd;
- add_incoming(fd, nit_recv, nit_name, j);
-
- a = malloc(6);
- memcpy(a, ifr.ifr_ifru.ifru_addr.sa_data, 6);
- TRACE(3, printf("eth address: %02x:%02x:%02x:%02x:%02x:%02x\n",
- a[0], a[1], a[2], a[3], a[4], a[5]))
- e = str_import(0, a, 6, 6);
- epattr(gaddr(e)) &= ~A_WRITE;
-
- array_put(0, nit_addr, j, e);
- j++;
- }
-
- if (!j) {
- decref(0, nit_addr);
- nit_addr = 0;
- decref(0, nit_name);
- nit_name = 0;
- return -1;
- }
- eplen(gaddr(nit_addr)) = j;
-
- return 0;
- }
-
-
- void
- nit_recv(int fd, eindex *m, eindex *o)
- {
- #define ETHFRAMESIZE 1500
- byteptr buf = malloc(ETHFRAMESIZE);
- eindex s;
- int len;
-
- len = read(fd, buf, ETHFRAMESIZE);
- if( len < 0 ) {
- *m = 0;
- perror("nit_getmsg");
- free(buf);
- return;
- }
-
- TRACE(3, printf("nit receive (%d bytes): ", len))
- TRACE(3, printf("%02x %02x %02x %02x %02x %02x\n",
- buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]))
-
- s = str_import(0, buf, len, ETHFRAMESIZE);
-
- *o = make_sub(0, s, 6);
- eplen(gaddr(*o)) = 6;
- *m = make_sub(0, s, 14);
- eplen(gaddr(*m)) = len - 14;
-
- decref(0, s);
- }
-
-
- int
- nit_send(sint chan, byteptr dest, byteptr packet, uint len)
- {
- struct strbuf data, ctrl;
- struct sockaddr sa;
-
- TRACE(3, printf("nit send (%d bytes, %02x:%02x:%02x:%02x:%02x:%02x)\n",
- len, dest[0], dest[1], dest[2], dest[3], dest[4], dest[5]))
-
- sa.sa_family = AF_UNSPEC;
-
- memcpy(sa.sa_data, dest, 6);
- sa.sa_data[12] = m0_eth_type>>8;
- sa.sa_data[13] = m0_eth_type & 0xff;
-
- data.buf = (char *) packet;
- data.len = len;
- ctrl.buf = (char *) &sa;
- ctrl.len = sizeof(sa);
-
- if( putmsg(nit_fd[chan], &ctrl, &data, 0) < 0 ) {
- perror("nit_putmsg");
- return -1;
- }
- return len;
- }
-
-
- static void
- nit_submit(mproc p, void *data, eindex m)
- {
- struct nit_data *n = (struct nit_data*) data;
- eptr mp = eaddr(p, m);
- uint len = eplen(mp);
-
- len = len > sizeof(eth_buf) ? sizeof(eth_buf) : len;
- if (epattr(mp) & (A_SUB | A_FRAG)) {
- str_export(p, eth_buf, m, 0, len);
- nit_send(n->chan, n->dest, eth_buf, len);
- } else
- nit_send(n->chan, n->dest, mp->V.str.s, len);
-
- dict_undef(0, channeldict, n->chankey);
- free(n);
- return;
- }
-
-
- eindex
- add_nit_channel(sint chan_no, byteptr dest)
- {
- eindex key;
- byte keybits[8];
- struct nit_data *n;
-
- random64(keybits);
- key = key_add(keybits);
-
- n = (struct nit_data*) malloc(sizeof(struct nit_data));
- n->chankey = key;
- n->chan = chan_no;
- memcpy(n->dest, dest, 6);
- new_channel(key, n, nit_submit);
-
- return key;
- }
-
- #endif
-