1 #include "sysconfig.h"
2 #include "sysdeps.h"
3
4 #include "ethernet.h"
5 #ifdef _WIN32
6 #ifdef FSUAE
7 #else
8 #include "win32_uaenet.h"
9 #endif
10 #endif
11 #include "threaddep/thread.h"
12 #include "options.h"
13 #include "sana2.h"
14 #include "uae/slirp.h"
15
16 #ifndef HAVE_INET_ATON
inet_aton(const char * cp,struct in_addr * ia)17 static int inet_aton(const char *cp, struct in_addr *ia)
18 {
19 uint32_t addr = inet_addr(cp);
20 if (addr == 0xffffffff)
21 return 0;
22 ia->s_addr = addr;
23 return 1;
24 }
25 #endif
26
27 struct ethernet_data
28 {
29 ethernet_gotfunc *gotfunc;
30 ethernet_getfunc *getfunc;
31 void *userdata;
32 };
33
34 #define SLIRP_PORT_OFFSET 0
35
36 static const int slirp_ports[] = { 21, 22, 23, 80, 0 };
37
38 static struct ethernet_data *slirp_data;
39 static bool slirp_inited;
40 uae_sem_t slirp_sem1, slirp_sem2;
41 static int netmode;
42
43 static struct netdriverdata slirpd =
44 {
45 UAENET_SLIRP,
46 _T("slirp"), _T("SLIRP User Mode NAT"),
47 1500,
48 { 0x00,0x00,0x00,50,51,52 },
49 1
50 };
51 static struct netdriverdata slirpd2 =
52 {
53 UAENET_SLIRP_INBOUND,
54 _T("slirp_inbound"), _T("SLIRP + Open ports (21-23,80)"),
55 1500,
56 { 0x00,0x00,0x00,50,51,52 },
57 1
58 };
59
slirp_output(const uint8_t * pkt,int pkt_len)60 void slirp_output (const uint8_t *pkt, int pkt_len)
61 {
62 if (!slirp_data)
63 return;
64 uae_sem_wait (&slirp_sem1);
65 slirp_data->gotfunc (slirp_data->userdata, pkt, pkt_len);
66 uae_sem_post (&slirp_sem1);
67 }
68
ethernet_trigger(struct netdriverdata * ndd,void * vsd)69 void ethernet_trigger (struct netdriverdata *ndd, void *vsd)
70 {
71 if (!ndd)
72 return;
73 switch (ndd->type)
74 {
75 #ifdef WITH_SLIRP
76 case UAENET_SLIRP:
77 case UAENET_SLIRP_INBOUND:
78 {
79 struct ethernet_data *ed = (struct ethernet_data*)vsd;
80 if (slirp_data) {
81 uae_u8 pkt[4000];
82 int len = sizeof pkt;
83 int v;
84 uae_sem_wait (&slirp_sem1);
85 v = slirp_data->getfunc(ed->userdata, pkt, &len);
86 uae_sem_post (&slirp_sem1);
87 if (v) {
88 uae_sem_wait (&slirp_sem2);
89 uae_slirp_input(pkt, len);
90 uae_sem_post (&slirp_sem2);
91 }
92 }
93 }
94 return;
95 #endif
96 #ifdef WITH_UAENET_PCAP
97 case UAENET_PCAP:
98 uaenet_trigger (vsd);
99 return;
100 #endif
101 }
102 }
103
ethernet_open(struct netdriverdata * ndd,void * vsd,void * user,ethernet_gotfunc * gotfunc,ethernet_getfunc * getfunc,int promiscuous)104 int ethernet_open (struct netdriverdata *ndd, void *vsd, void *user, ethernet_gotfunc *gotfunc, ethernet_getfunc *getfunc, int promiscuous)
105 {
106 switch (ndd->type)
107 {
108 #ifdef WITH_SLIRP
109 case UAENET_SLIRP:
110 case UAENET_SLIRP_INBOUND:
111 {
112 struct ethernet_data *ed = (struct ethernet_data*)vsd;
113 ed->gotfunc = gotfunc;
114 ed->getfunc = getfunc;
115 ed->userdata = user;
116 slirp_data = ed;
117 uae_sem_init (&slirp_sem1, 0, 1);
118 uae_sem_init (&slirp_sem2, 0, 1);
119 uae_slirp_init();
120 for (int i = 0; i < MAX_SLIRP_REDIRS; i++) {
121 struct slirp_redir *sr = &currprefs.slirp_redirs[i];
122 if (sr->proto) {
123 struct in_addr a;
124 if (sr->srcport == 0) {
125 inet_aton("10.0.2.15", &a);
126 uae_slirp_redir (0, sr->dstport, a, sr->dstport);
127 } else {
128 #ifdef HAVE_STRUCT_IN_ADDR_S_UN
129 a.S_un.S_addr = sr->addr;
130 #else
131 a.s_addr = sr->addr;
132 #endif
133 uae_slirp_redir (sr->proto == 1 ? 0 : 1, sr->dstport, a, sr->srcport);
134 }
135 }
136 }
137 if (ndd->type == UAENET_SLIRP_INBOUND) {
138 struct in_addr a;
139 inet_aton("10.0.2.15", &a);
140 for (int i = 0; slirp_ports[i]; i++) {
141 int port = slirp_ports[i];
142 int j;
143 for (j = 0; j < MAX_SLIRP_REDIRS; j++) {
144 struct slirp_redir *sr = &currprefs.slirp_redirs[j];
145 if (sr->proto && sr->dstport == port)
146 break;
147 }
148 if (j == MAX_SLIRP_REDIRS)
149 uae_slirp_redir (0, port + SLIRP_PORT_OFFSET, a, port);
150 }
151 }
152 netmode = ndd->type;
153 uae_slirp_start ();
154 }
155 return 1;
156 #endif
157 #ifdef WITH_UAENET_PCAP
158 case UAENET_PCAP:
159 if (uaenet_open (vsd, ndd, user, gotfunc, getfunc, promiscuous)) {
160 netmode = ndd->type;
161 return 1;
162 }
163 return 0;
164 #endif
165 }
166 return 0;
167 }
168
ethernet_close(struct netdriverdata * ndd,void * vsd)169 void ethernet_close (struct netdriverdata *ndd, void *vsd)
170 {
171 if (!ndd)
172 return;
173 switch (ndd->type)
174 {
175 #ifdef WITH_SLIRP
176 case UAENET_SLIRP:
177 case UAENET_SLIRP_INBOUND:
178 if (slirp_data) {
179 slirp_data = NULL;
180 uae_slirp_end ();
181 uae_slirp_cleanup ();
182 uae_sem_destroy (&slirp_sem1);
183 uae_sem_destroy (&slirp_sem2);
184 }
185 return;
186 #endif
187 #ifdef WITH_UAENET_PCAP
188 case UAENET_PCAP:
189 return uaenet_close (vsd);
190 #endif
191 }
192 }
193
ethernet_enumerate_free(void)194 void ethernet_enumerate_free (void)
195 {
196 #ifdef WITH_UAENET_PCAP
197 uaenet_enumerate_free ();
198 #endif
199 }
200
ethernet_enumerate(struct netdriverdata ** nddp,const TCHAR * name)201 bool ethernet_enumerate (struct netdriverdata **nddp, const TCHAR *name)
202 {
203 int j;
204 struct netdriverdata *nd;
205 if (name) {
206 netmode = 0;
207 *nddp = NULL;
208 if (!_tcsicmp (slirpd.name, name))
209 *nddp = &slirpd;
210 if (!_tcsicmp (slirpd2.name, name))
211 *nddp = &slirpd2;
212 #ifdef WITH_UAENET_PCAP
213 if (*nddp == NULL)
214 *nddp = uaenet_enumerate (name);
215 #endif
216 if (*nddp) {
217 netmode = (*nddp)->type;
218 return true;
219 }
220 return false;
221 }
222 j = 0;
223 nddp[j++] = &slirpd;
224 nddp[j++] = &slirpd2;
225 #ifdef WITH_UAENET_PCAP
226 nd = uaenet_enumerate (NULL);
227 if (nd) {
228 for (int i = 0; i < MAX_TOTAL_NET_DEVICES; i++) {
229 if (nd[i].active)
230 nddp[j++] = &nd[i];
231 }
232 }
233 #endif
234 nddp[j] = NULL;
235 return true;
236 }
237
ethernet_close_driver(struct netdriverdata * ndd)238 void ethernet_close_driver (struct netdriverdata *ndd)
239 {
240 switch (ndd->type)
241 {
242 case UAENET_SLIRP:
243 case UAENET_SLIRP_INBOUND:
244 return;
245 #ifdef WITH_UAENET_PCAP
246 case UAENET_PCAP:
247 return uaenet_close_driver (ndd);
248 #endif
249 }
250 netmode = 0;
251 }
252
ethernet_getdatalenght(struct netdriverdata * ndd)253 int ethernet_getdatalenght (struct netdriverdata *ndd)
254 {
255 switch (ndd->type)
256 {
257 case UAENET_SLIRP:
258 case UAENET_SLIRP_INBOUND:
259 return sizeof (struct ethernet_data);
260 #ifdef WITH_UAENET_PCAP
261 case UAENET_PCAP:
262 return uaenet_getdatalenght ();
263 #endif
264 }
265 return 0;
266 }
267