00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "config.h"
00010
00011 #include <netinet/in.h>
00012
00013 #include <errno.h>
00014 #include <stdio.h>
00015 #include <stdlib.h>
00016 #include <string.h>
00017 #include <unistd.h>
00018
00019 #include "dnet.h"
00020
00021 struct ip_handle {
00022 int fd;
00023 };
00024
00025 ip_t *
00026 ip_open(void)
00027 {
00028 ip_t *i;
00029 int n, len;
00030
00031 if ((i = calloc(1, sizeof(*i))) == NULL)
00032 return (NULL);
00033
00034 if ((i->fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0)
00035 return (ip_close(i));
00036 #ifdef IP_HDRINCL
00037 n = 1;
00038 if (setsockopt(i->fd, IPPROTO_IP, IP_HDRINCL, &n, sizeof(n)) < 0)
00039 return (ip_close(i));
00040 #endif
00041 #ifdef SO_SNDBUF
00042 len = sizeof(n);
00043 if (getsockopt(i->fd, SOL_SOCKET, SO_SNDBUF, &n, &len) < 0)
00044 return (ip_close(i));
00045
00046 for (n += 128; n < 1048576; n += 128) {
00047 if (setsockopt(i->fd, SOL_SOCKET, SO_SNDBUF, &n, len) < 0) {
00048 if (errno == ENOBUFS)
00049 break;
00050 return (ip_close(i));
00051 }
00052 }
00053 #endif
00054 #ifdef SO_BROADCAST
00055 n = 1;
00056 if (setsockopt(i->fd, SOL_SOCKET, SO_BROADCAST, &n, sizeof(n)) < 0)
00057 return (ip_close(i));
00058 #endif
00059 return (i);
00060 }
00061
00062 ssize_t
00063 ip_send(ip_t *i, const void *buf, size_t len)
00064 {
00065 struct ip_hdr *ip;
00066 struct sockaddr_in sin;
00067
00068 ip = (struct ip_hdr *)buf;
00069
00070 memset(&sin, 0, sizeof(sin));
00071 #ifdef HAVE_SOCKADDR_SA_LEN
00072 sin.sin_len = sizeof(sin);
00073 #endif
00074 sin.sin_family = AF_INET;
00075 sin.sin_addr.s_addr = ip->ip_dst;
00076
00077 #ifdef HAVE_RAWIP_HOST_OFFLEN
00078 ip->ip_len = ntohs(ip->ip_len);
00079 ip->ip_off = ntohs(ip->ip_off);
00080
00081 len = sendto(i->fd, buf, len, 0,
00082 (struct sockaddr *)&sin, sizeof(sin));
00083
00084 ip->ip_len = htons(ip->ip_len);
00085 ip->ip_off = htons(ip->ip_off);
00086
00087 return (len);
00088 #else
00089 return (sendto(i->fd, buf, len, 0,
00090 (struct sockaddr *)&sin, sizeof(sin)));
00091 #endif
00092 }
00093
00094 ip_t *
00095 ip_close(ip_t *i)
00096 {
00097 if (i != NULL) {
00098 if (i->fd >= 0)
00099 close(i->fd);
00100 free(i);
00101 }
00102 return (NULL);
00103 }