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;
100 struct sockaddr_in ip_from;
103 CK_IFTYPE2(ifp,IF_TYPE_IPIP,IF_TYPE_IPUDP);
107 (void)memset((char *)&ip_from, 0, sizeof(struct sockaddr));
108 ip_from.sin_family = AF_INET;
109 fromlen = sizeof ip_from;
111 n = recvfrom(ifp->fd, (char *)buf, MAX_SIZE, 0,(struct sockaddr *)&ip_from, &fromlen);
114 if(errno==EINTR)return 0;
115 if(errno==EWOULDBLOCK)return 0;
116 PERR("recvfrom: on socket");
122 if(ifp->type == IF_TYPE_IPUDP){
126 ipptr = (struct iphdr *)buf;
127 hdr_len = 4 * ipptr->ihl;
129 ipptr = (struct ip *)buf;
130 hdr_len = 4 * ipptr->ip_hl;
136 (void)memcpy((char *)m->msg,(char *)p, n);
138 (void)memcpy( (char *)&(m->fip), (char *)&ip_from.sin_addr, 4);
139 m->fport = ip_from.sin_port;
144 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
145 * write data from to the specified interface. Return as soon as possible.
146 * The buffer provided will be a complete IP datagram.
147 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
150 struct interface *ifp;
154 struct sockaddr_in ip_to;
157 CK_IFTYPE2(ifp,IF_TYPE_IPIP,IF_TYPE_IPUDP);
161 if(m->length<=0)return 0;
164 syslog(LOG_WARNING,"attempt to send to IP address 0.0.0.0");
168 if((ifp->type==IF_TYPE_IPUDP)&&(m->tport==0)){
169 syslog(LOG_WARNING,"attempt to send to UDP port 0");
173 (void)memset( (char *)&ip_to, 0, sizeof(struct sockaddr) );
174 ip_to.sin_family = AF_INET;
175 ip_to.sin_port = m->tport;
176 (void)memcpy((char *)&ip_to.sin_addr, (char *)&(m->tip), 4);
178 n = sendto(ifp->fd, (char *)m->msg, m->length, 0,
179 (struct sockaddr *)&ip_to, sizeof ip_to);
181 /* Log errors but don't die, since most errors are transient */
183 unsigned char *p = (unsigned char *)&m->tip;
185 "ip_send(dest:%d.%d.%d.%d) sendto(): %s",
186 p[0], p[1], p[2], p[3], strerror (errno) ) ;
188 return 0; /* Who cares? Continue. */