1 /* ip.c system IP or UDP level stuff
3 * $Id: ip.c,v 1.4 1995/03/19 17:21:06 bdale Exp $
5 * Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
6 * This software may be freely used, distributed, or modified, providing
7 * this header is not removed.
9 * Added support for Linux - Ron Atkinson N8FOW
14 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <netinet/in_systm.h>
19 #include <netinet/ip.h>
29 #define FNDELAY O_NDELAY
34 #define IF_NAME "ip" /* for use with the error checking macros */
37 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
38 * open and initialize the IO interface. Return -1 for error.
39 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
42 struct interface *ifp;
44 struct sockaddr_in ip_udpbind;
47 CK_IFTYPE2(ifp,IF_TYPE_IPIP,IF_TYPE_IPUDP);
49 if((ifp->status & IF_STAT_OPEN)) return 1;
51 if(ifp->type == IF_TYPE_IPUDP){
52 ifp->fd = socket(AF_INET, SOCK_DGRAM, 0);
54 ifp->fd = socket(AF_INET, SOCK_RAW, ifp->unit);
57 PERR("opening socket");
61 if (fcntl(ifp->fd, F_SETFL, FNDELAY) < 0) {
62 PERR("setting non-blocking I/O on raw socket");
66 if(ifp->type == IF_TYPE_IPUDP){
67 (void)memset( (char *)&ip_udpbind, 0, sizeof(struct sockaddr) );
68 ip_udpbind.sin_addr.s_addr = INADDR_ANY;
69 ip_udpbind.sin_family = AF_INET;
70 ip_udpbind.sin_port = htons((unsigned short)ifp->unit);
71 if(bind(ifp->fd,(struct sockaddr *)&ip_udpbind,sizeof ip_udpbind)<0){
72 PERR("binding udp socket");
77 ifp->status = IF_STAT_OPEN;
83 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
84 * Read data from the specified interface. Return a complete IP datagram.
85 * If the datagram is not complete, then don't return anything.
86 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
89 struct interface *ifp;
92 unsigned char buf[MAX_SIZE], *p;
93 int n, hdr_len, fromlen;
99 struct sockaddr_in ip_from;
102 CK_IFTYPE2(ifp,IF_TYPE_IPIP,IF_TYPE_IPUDP);
106 (void)memset((char *)&ip_from, 0, sizeof(struct sockaddr));
107 ip_from.sin_family = AF_INET;
108 fromlen = sizeof ip_from;
110 n = recvfrom(ifp->fd, (char *)buf, MAX_SIZE, 0,(struct sockaddr *)&ip_from, &fromlen);
113 if(errno==EINTR)return 0;
114 if(errno==EWOULDBLOCK)return 0;
115 PERR("recvfrom: on socket");
121 if(ifp->type == IF_TYPE_IPUDP){
125 ipptr = (struct iphdr *)buf;
126 hdr_len = 4 * ipptr->ihl;
128 ipptr = (struct ip *)buf;
129 hdr_len = 4 * ipptr->ip_hl;
135 (void)memcpy((char *)m->msg,(char *)p, n);
137 (void)memcpy( (char *)&(m->fip), (char *)&ip_from.sin_addr, 4);
138 m->fport = ip_from.sin_port;
143 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
144 * write data from to the specified interface. Return as soon as possible.
145 * The buffer provided will be a complete IP datagram.
146 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
149 struct interface *ifp;
153 struct sockaddr_in ip_to;
156 CK_IFTYPE2(ifp,IF_TYPE_IPIP,IF_TYPE_IPUDP);
160 if(m->length<=0)return 0;
163 syslog(LOG_WARNING,"attempt to send to IP address 0.0.0.0");
167 if((ifp->type==IF_TYPE_IPUDP)&&(m->tport==0)){
168 syslog(LOG_WARNING,"attempt to send to UDP port 0");
172 (void)memset( (char *)&ip_to, 0, sizeof(struct sockaddr) );
173 ip_to.sin_family = AF_INET;
174 ip_to.sin_port = m->tport;
175 (void)memcpy((char *)&ip_to.sin_addr, (char *)&(m->tip), 4);
177 n = sendto(ifp->fd, (char *)m->msg, m->length, 0,
178 (struct sockaddr *)&ip_to, sizeof ip_to);
180 /* Log errors but don't die, since most errors are transient */
182 unsigned char *p = (unsigned char *)&m->tip;
184 "ip_send(dest:%d.%d.%d.%d) sendto(): %s",
185 p[0], p[1], p[2], p[3], strerror (errno) ) ;
187 return 0; /* Who cares? Continue. */