📄 slipbsd.c
字号:
/* $Header: /usr/cvsroot/target/src/wrn/wm/demo/lib/slipbsd.c,v 1.3 2003/01/15 14:04:34 josh Exp $ *//* * Copyright (C) 1999-2005 Wind River Systems, Inc. * All rights reserved. Provided under license only. * Distribution or other use of this software is only * permitted pursuant to the terms of a license agreement * from Wind River Systems (and is otherwise prohibited). * Refer to that license agreement for terms of use. *//**************************************************************************** * Copyright 1993-1997 Epilogue Technology Corporation. * Copyright 1998 Integrated Systems, Inc. * All rights reserved. ****************************************************************************//* * $Log: slipbsd.c,v $ * Revision 1.3 2003/01/15 14:04:34 josh * directory structure shifting * * Revision 1.2 2001/11/08 15:56:26 tneale * Updated for newest file layout * * Revision 1.1.1.1 2001/11/05 17:48:43 tneale * Tornado shuffle * * Revision 2.14 2001/01/19 22:23:51 paul * Update copyright. * * Revision 2.13 2000/10/16 19:21:54 paul * Restore sockets and mempool code. * * Revision 2.12 2000/03/17 00:12:44 meister * Update copyright message * * Revision 2.11 2000/03/13 21:22:08 paul * Removed some code that we are no longer working on. * * Revision 2.10 1999/11/05 22:29:07 paul * Updated driver structs to reflect conditional backwards-compatibility * fields and new fields. * * Revision 2.9 1999/04/07 14:57:00 sra * Update COM_DEV_NAME to something sane. * * Revision 2.8 1998/02/25 15:21:50 sra * Finish moving types.h, bug.h, and bugdef.h to common/h/. * * Revision 2.7 1998/02/25 04:57:37 sra * Update copyrights. * * Revision 2.6 1997/03/20 06:53:10 sra * DFARS-safe copyright text. Zap! * * Revision 2.5 1997/02/25 10:58:16 sra * Update copyright notice, dust under the bed. * * Revision 2.4 1997/02/19 08:10:29 sra * More fun merging snmptalk into snark, general snark cleanup. * * Revision 2.3 1996/11/13 15:09:16 mrf * Changes necessary to make snoop support work on Irix 5.x include * addition of snoop driver code and port to somewhat wacky Irix * curses implementation. * * Revision 2.2 1996/03/22 10:05:39 sra * Update copyrights prior to Attache 3.2 release. * * Revision 2.1 1995/11/16 00:33:13 sra * Fix a format string to make gcc -paranoid happier. * Rearrange file header per current conventions. * * Revision 2.0 1995/05/10 22:38:15 sra * Attache release 3.0. * * Revision 1.4 1995/01/06 00:52:48 sra * Update copyright notice for 2.1 release. * * Revision 1.3 1994/09/04 06:13:38 sra * Clean up antique type names and install macros. * * Revision 1.2 1994/01/09 23:57:29 sra * Add support for NIT under SunOS 4.1.2. * * Revision 1.1 1993/07/05 21:53:30 sra * Initial revision * *//* [clearcase]modification history-------------------01a,19apr05,job update copyright notices*//* * Serial Line IP (SLIP) interface for snark under BSD-derived systems. * * This code has only been tested under NetBSD 0.8. It should work on * any BSD-derived system with minor modifications. */#include <wrn/wm/attache/config.h>#include <wrn/wm/common/types.h>#include <wrn/wm/attache/mib.h>#include <wrn/wm/attache/timer.h>#include <wrn/wm/attache/packet.h>#include <wrn/wm/attache/net.h>#include <wrn/wm/attache/glue.h>#include <wrn/wm/attache/route.h>#include <wrn/wm/attache/ip.h>#include <wrn/wm/attache/loop.h>#include <stdio.h>#include <sgtty.h>#include <sys/types.h>#include <sys/time.h>#include <errno.h>#include <fcntl.h>#include <sys/file.h>#include <unistd.h>#include <wrn/wm/demo/bsdif.h>#include <wrn/wm/demo/slipbsd.h>#define PF_SLIP_BOP 0x1000#ifndef COM_DEV_NAME#define COM_DEV_NAME "/dev/cuaa"#endif/* * SLIP control structure, hangs off net->specific->private. */#ifndef SNARKBSD_SLIP_IBUFLEN#define SNARKBSD_SLIP_IBUFLEN 1000#endif#ifndef SNARKBSD_SLIP_OBUFLEN#define SNARKBSD_SLIP_OBUFLEN 6000#endifstruct slipctl { struct net *net; unsigned iescaped : 1; unsigned idiscard : 1; unsigned oescaped : 1; packet *ipkt, *opkt_head, **opkt_tail; int ilen, olen; unsigned char *ibp, *obp; unsigned char ibuf[SNARKBSD_SLIP_IBUFLEN], obuf[SNARKBSD_SLIP_OBUFLEN];};/* * SLIP framing characters */#define SLIP_END 0300#define SLIP_ESC 0333#define SLIP_ENC_END 0334#define SLIP_ENC_ESC 0335/* * Decode a buffer of data into zero or more Attache packet buffers. * Most of the hair is just checking for weird boundary conditions. */#define DOCHAR(x) \ if (sp->idiscard) { \ continue; \ } else if (p->pkt_data < p->pkt_buffer + p->pkt_buflen) { \ *p->pkt_data++ = (x); \ } else { \ sp->idiscard = 1; \ continue; \ }static packet *slip_decode (struct net *net, unsigned char *buf, int len, int *used){ struct bsdif *bif = net->specific; struct slipctl *sp = bif->private; unsigned char *bob = buf, *eob = buf + len; packet *p; while (buf < eob) { if (sp->ipkt == 0 && (sp->ipkt = pkt_alloc(net->driver->maxlen)) == 0) break; /* Oops, no packet buffers */ p = sp->ipkt; if (sp->iescaped) { /* Was escaped */ sp->iescaped = 0; /* ain't no more */ switch (*buf++) { case SLIP_ENC_END: DOCHAR(SLIP_END); /* Escaped END character */ continue; case SLIP_ENC_ESC: DOCHAR(SLIP_ESC); /* Escaped ESC character */ continue; default: sp->idiscard = 1; /* Escaped garbage, packet be bogus */ continue; } } else { switch (*buf++) { case SLIP_END: if (!sp->idiscard && p->pkt_data > p->pkt_buffer) { sp->ipkt = 0; p->pkt_datalen = p->pkt_data - p->pkt_buffer; p->pkt_data = p->pkt_buffer; if (used) *used = buf - bob; return p; /* Happy packet */ } sp->idiscard = 0; /* Bogus packet now history */ p->pkt_data = p->pkt_buffer; continue; case SLIP_ESC: sp->iescaped = 1; /* An escaping byte! */ continue; default: DOCHAR(*(buf-1)); /* A normal boring byte */ continue; } } } if (used) *used = buf - bob; return 0; /* Yes, we have no packet today */}#undef DOCHAR/* * Encode zero or more Attache packet buffers into a data buffer. * Packets will have been queued for us by slip_send(). */#define DOCHAR(x) \ do { *buf++ = (x); if (buf == eob) return (buf - bob); } while (0)static int slip_encode(struct net *net, unsigned char *buf, int len){ struct bsdif *bif = net->specific; struct slipctl *sp = bif->private; unsigned char *bob = buf, *eob = buf + len; packet *p; if (len <= 0) return 0; while ((p = sp->opkt_head) != 0) { /* * Send framing sequence before a new packet, to flush line noise. */ if ((p->pkt_flags & PF_SLIP_BOP) != 0) { p->pkt_flags &= ~PF_SLIP_BOP; DOCHAR(SLIP_END); } /* * Process data in this packet. */ while (p->pkt_datalen > 0) { if (sp->oescaped) { sp->oescaped = 0; /* Was escaped, ain't no more */ switch (*p->pkt_data++) { case SLIP_END: /* Encoding an END octet */ DOCHAR(SLIP_ENC_END); break; case SLIP_ESC: /* Encoding an ESC octet */ DOCHAR(SLIP_ENC_ESC); break; } } else { switch (*p->pkt_data) { case SLIP_END: /* I need an escape */ case SLIP_ESC: sp->oescaped = 1; DOCHAR(SLIP_ESC); continue; /* Doesn't count as sent yet */ default: DOCHAR(*p->pkt_data++); /* Normal octet, send it */ } } p->pkt_datalen--; /* One less octet to feed */ } /* * No more data in current packet, so send framing sequence * and proceed with next packet in the output queue. */ DOCHAR(SLIP_END); if ((sp->opkt_head = p->pkt_link) == 0) sp->opkt_tail = &sp->opkt_head; pkt_free(p); } return buf - bob;}#undef DOCHAR/* * Process whatever incoming SLIP data we can without blocking, * passing zero or more Attache packets to ip_rcv(). */static void slip_rcv(struct net *net){ struct bsdif *bif = net->specific; struct slipctl *sp = bif->private; packet *p; int n; if (sp->ilen <= 0) { do { n = read(bif->fd, (char *) sp->ibuf, sizeof(sp->ibuf)); } while (n < 0 && errno == EINTR); if (n == 0 || (n < 0 && errno != EWOULDBLOCK)) { bif->flags &= ~BSDIF_READ; return; } sp->ilen = n; sp->ibp = sp->ibuf; } while (sp->ilen > 0) { if ((p = slip_decode(net, sp->ibp, sp->ilen, &n)) != 0) { p->pkt_n = net; ip_rcv(p); } if (n == 0) /* out of packet buffers, try again later */ break; sp->ibp += n; /* count what we consumed */ sp->ilen -= n; }}/* * Process whatever outgoing Attache packets we can without blocking. * Generates zero or more writes of encoded SLIP data. */static void slip_snd(struct net *net){ struct bsdif *bif = net->specific; struct slipctl *sp = bif->private; int n; for (;;) { if (sp->olen == 0) { if ((n = slip_encode(net, sp->obuf, sizeof(sp->obuf))) == 0) break; sp->olen = n; sp->obp = sp->obuf; } do { n = write(bif->fd, sp->obp, sp->olen); } while (n < 0 && errno == EINTR); if (n <= 0) break; sp->obp += n; sp->olen -= n; } if (n == 0 || (n < 0 && errno != EWOULDBLOCK)) bif->flags &= ~BSDIF_WRITE;}/* * Handle events detected by generic NetBSD I/O loop. * The flags tell us what kind of event happened, we call the * non-blocking I/O routines to do the real work. */static void slip_handler(int fd, void *net, unsigned flags){ if ((flags & BSDIF_WRITE) != 0) slip_snd(net); if ((flags & BSDIF_READ) != 0) slip_rcv(net);}/* * Convert between raw line speed numbers and NetBSD line speed codes. * The second argument names the thing you want as the return value. */enum speed_index { slip_speed_number, slip_speed_symbol };static int slip_speed(int speed, enum speed_index speed_index){ int i; static int table[][2] = { { 1200, B1200 }, { 2400, B2400 }, { 4800, B4800 }, { 9600, B9600 }, { 19200, EXTA }, { 38400, EXTB } }; for (i = 0; i < sizeof(table)/sizeof(*table); ++i) if (table[i][!speed_index] == speed) return table[i][speed_index]; return 0;}/* * Attache device driver routines. */static void slip_ip_send(struct net *net, packet *p, inaddr_t host){ p->pkt_n = net; (*net->driver->send)(p); /* Not much to do here, huh? */}static void slip_send(packet *p){ struct net *net = p->pkt_n; struct bsdif *bif = net->specific; struct slipctl *sp = bif->private; p->pkt_flags |= PF_SLIP_BOP; /* Flag that this is a new packet */ p->pkt_link = 0; /* Stuff this packet into the */ *sp->opkt_tail = p; /* output queue */ sp->opkt_tail = &p->pkt_link; bif->flags |= BSDIF_WRITE; /* Now interested in output events */ slip_snd(net); /* Send what we can right away */}static void slip_close(struct net *net){ struct bsdif *bif = net->specific; net->flags |= NF_DRIVER_DOWN; bif->flags &= ~(BSDIF_READ | BSDIF_WRITE); if (bif->fd >= 0) { (void) close(bif->fd); /* Clean up our file if we had one */ bif->fd = -1; } if (bif->private) { GLUE_FREE(bif->private); /* Release our memory if we had any */ bif->private = 0; }}static void slip_init(struct net *net){ struct bsdif *bif = net->specific; struct slipctl *sp; struct sgttyb sgtty; char name[sizeof(COM_DEV_NAME)+4]; int speed = slip_speed(net->speed, slip_speed_symbol); net->flags |= NF_DRIVER_DOWN; sprintf(name, "%s%d", COM_DEV_NAME, net->instance); if (!speed) { fprintf(stderr, "line speed %lu not supported\n", net->speed); return; } if ((bif->private = sp = GLUE_ALLOC(sizeof(*sp))) == 0) { fprintf(stderr, "couldn't allocate slip control structure\n"); return; } MEMSET(sp, 0, sizeof(*sp)); sp->opkt_tail = &sp->opkt_head; sp->net = net; sgtty.sg_flags = RAW | ANYP; sgtty.sg_ispeed = sgtty.sg_ospeed = speed; if ((bif->fd = open(name, O_RDWR, 0660)) < 0) { /* |O_NONBLOCK */ perror("couldn't open slip device"); } else if (ioctl(bif->fd, TIOCSETP, &sgtty) < 0) { perror("couldn't set slip line flags and speed"); } else if (fcntl(bif->fd, F_SETFL, FNDELAY) < 0) { perror("unable to set slip pty non-blocking"); } else { bif->handler = slip_handler; bif->flags |= BSDIF_READ; net->flags &= ~NF_DRIVER_DOWN; return; /* success */ } slip_close(net); /* failure */}static struct driver slip_driver = { slip_init, /* Init routine */ slip_send, /* Raw send routine */ slip_ip_send, /* IP packet send routine */ 0, 0, /* ARP and test close routines */ slip_close, /* Close routine */ "sl", /* Driver name prefix */ "Serial Line IP", /* Driver name */ 0, 0, /* Net header and trailer lengths */ 296, /* Max packet size */ IF_SLIP, /* MIB interface type */ 0, /* ARP hardware type (none) */ 0, /* media control */ 0, /* IPv6 send */ 0 /* IPv4 send */};void slip_driver_find (void (*config)(char *, struct driver *, int, bits16_t, unsigned, bits32_t)){ char name[sizeof(COM_DEV_NAME)+4]; struct sgttyb sgtty; int fd, speed, instance; for (instance = 0; ; instance++) { sprintf(name, "%s%d", COM_DEV_NAME, instance); if ((fd = open(name, O_RDONLY | O_NONBLOCK)) < 0) { if (errno == ENOENT) return; continue; } speed = ((ioctl(fd, TIOCGETP, &sgtty) < 0) ? 0 : slip_speed(sgtty.sg_ispeed, slip_speed_number)); (void) close(fd); if (speed == 0) continue; sprintf(name, "%d", instance); config(name, &slip_driver, instance, 0, slip_driver.maxlen - slip_driver.lnh - slip_driver.lnt, speed); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -