1 /*
2 * tun-solaris.c
3 *
4 * Copyright (c) 2001 Dug Song <dugsong@monkey.org>
5 *
6 * $Id: tun-solaris.c,v 1.3 2002/03/09 04:41:40 dugsong Exp $
7 */
8
9 #include <sys/types.h>
10 #include <sys/ioctl.h>
11 #include <sys/socket.h>
12 #include <sys/sockio.h>
13
14 #include <net/if.h>
15 #include <net/if_tun.h>
16
17 #include <dnet.h>
18 #include <event.h>
19
20 #include <fcntl.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <stropts.h>
25 #include <unistd.h>
26
27 #include "tun.h"
28
29 #define DEV_TUN "/dev/tun"
30 #define DEV_IP "/dev/ip"
31
32 struct tun {
33 int fd;
34 int ip_fd;
35 int if_fd;
36
37 struct event ev;
38 tun_handler callback;
39 void *arg;
40 };
41
42 tun_t *
tun_open(struct addr * src,struct addr * dst,int mtu)43 tun_open(struct addr *src, struct addr *dst, int mtu)
44 {
45 tun_t *tun;
46 char cmd[512];
47 int ppa;
48
49 if ((tun = calloc(1, sizeof(*tun))) == NULL)
50 return (NULL);
51
52 if ((tun->fd = open(DEV_TUN, O_RDWR, 0)) < 0)
53 return (tun_close(tun));
54
55 if ((tun->ip_fd = open(DEV_IP, O_RDWR, 0)) < 0)
56 return (tun_close(tun));
57
58 if ((ppa = ioctl(tun->fd, TUNNEWPPA, ppa)) < 0)
59 return (tun_close(tun));
60
61 if ((tun->if_fd = open(DEV_TUN, O_RDWR, 0)) < 0)
62 return (tun_close(tun));
63
64 if (ioctl(tun->if_fd, I_PUSH, "ip") < 0)
65 return (tun_close(tun));
66
67 if (ioctl(tun->if_fd, IF_UNITSEL, (char *)&ppa) < 0)
68 return (tun_close(tun));
69
70 if (ioctl(tun->ip_fd, I_LINK, tun->if_fd) < 0)
71 return (tun_close(tun));
72
73 snprintf(cmd, sizeof(cmd), "ifconfig tun%d %s/32 %s mtu %d up",
74 ppa, addr_ntoa(src), addr_ntoa(dst), mtu);
75
76 if (system(cmd) < 0)
77 return (tun_close(tun));
78
79 return (tun);
80 }
81
82 static void
_tun_recv(int fd,short event,void * arg)83 _tun_recv(int fd, short event, void *arg)
84 {
85 tun_t *tun = (tun_t *)arg;
86 struct strbuf sbuf;
87 u_char buf[4096];
88 int flags = 0;
89
90 event_add(&tun->ev, NULL);
91
92 sbuf.buf = buf;
93 sbuf.maxlen = sizeof(buf);
94
95 if (getmsg(fd, NULL, &sbuf, &flags) >= 0)
96 (*tun->callback)(sbuf.buf, sbuf.len, tun->arg);
97 }
98
99 int
tun_register(tun_t * tun,tun_handler callback,void * arg)100 tun_register(tun_t *tun, tun_handler callback, void *arg)
101 {
102 tun->callback = callback;
103 tun->arg = arg;
104
105 event_set(&tun->ev, tun->fd, EV_READ, _tun_recv, tun);
106 event_add(&tun->ev, NULL);
107
108 return (0);
109 }
110
111 tun_t *
tun_close(tun_t * tun)112 tun_close(tun_t *tun)
113 {
114 if (event_initialized(&tun->ev))
115 event_del(&tun->ev);
116 if (tun->if_fd > 0)
117 close(tun->if_fd);
118 if (tun->ip_fd > 0)
119 close(tun->ip_fd);
120 if (tun->fd > 0)
121 close(tun->fd);
122 free(tun);
123
124 return (NULL);
125 }
126