2 * Copyright (C) 2009 Luigi Rizzo, Marta Carbone, Universita` di Pisa
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $Id: bsd_compat.c 11530 2012-08-01 10:29:32Z luigi $
29 * kernel variables and functions that are not available in linux.
32 #include <sys/cdefs.h>
33 #include <asm/div64.h> /* do_div on 2.4 */
34 #include <linux/random.h> /* get_random_bytes on 2.4 */
35 #include <netinet/ip_fw.h>
36 #include <netinet/ip_dummynet.h>
37 #include <sys/malloc.h>
40 * gettimeofday would be in sys/time.h but it is not
41 * visible if _KERNEL is defined
43 int gettimeofday(struct timeval *, struct timezone *);
45 int ticks; /* kernel ticks counter */
46 int hz = 1000; /* default clock time */
47 long tick = 1000; /* XXX is this 100000/hz ? */
49 struct timeval boottime;
51 int ip_defttl = 64; /* XXX set default value */
54 u_long in_ifaddrhmask; /* mask for hash table */
55 struct in_ifaddrhashhead *in_ifaddrhashtbl; /* inet addr hash table */
57 u_int rt_numfibs = RT_NUMFIBS;
61 * We make pfil_head_get return a non-null pointer, which is then ignored
62 * in our 'add-hook' routines.
65 typedef int (pfil_hook_t)
66 (void *, struct mbuf **, struct ifnet *, int, struct inpcb *);
69 pfil_head_get(int proto, u_long flags)
72 return (struct pfil_head *)&dummy;
76 pfil_add_hook(pfil_hook_t *func, void *arg, int dir, struct pfil_head *h)
82 pfil_remove_hook(pfil_hook_t *func, void *arg, int dir, struct pfil_head *h)
87 /* define empty body for kernel function */
89 priv_check(struct thread *td, int priv)
95 securelevel_ge(struct ucred *cr, int level)
101 sysctl_handle_int(SYSCTL_HANDLER_ARGS)
107 sysctl_handle_long(SYSCTL_HANDLER_ARGS)
113 ether_demux(struct ifnet *ifp, struct mbuf *m)
119 ether_output_frame(struct ifnet *ifp, struct mbuf *m)
125 in_rtalloc_ign(struct route *ro, u_long ignflags, u_int fibnum)
131 icmp_error(struct mbuf *n, int type, int code, uint32_t dest, int mtu)
137 in_cksum_skip(struct mbuf *m, int len, int skip)
143 in_cksum_hdr(struct ip *ip)
149 * we don't really reassemble, just return whatever we had.
152 ip_reass(struct mbuf *clone)
156 #ifdef INP_LOCK_ASSERT
157 #undef INP_LOCK_ASSERT
158 #define INP_LOCK_ASSERT(a)
161 /* credentials check */
162 #include <netinet/ip_fw.h>
165 cred_check(void *_insn, int proto, struct ifnet *oif,
166 struct in_addr dst_ip, u_int16_t dst_port, struct in_addr src_ip,
167 u_int16_t src_port, struct bsd_ucred *u, int *ugid_lookupp,
171 ipfw_insn_u32 *insn = (ipfw_insn_u32 *)_insn;
173 if (*ugid_lookupp == 0) { /* actively lookup and copy in cache */
174 /* returns null if any element of the chain up to file is null.
175 * if sk != NULL then we also have a reference
177 *ugid_lookupp = linux_lookup(proto,
178 src_ip.s_addr, htons(src_port),
179 dst_ip.s_addr, htons(dst_port),
180 skb, oif ? 1 : 0, u);
182 if (*ugid_lookupp < 0)
185 if (insn->o.opcode == O_UID)
186 match = (u->uid == (uid_t)insn->d[0]);
187 else if (insn->o.opcode == O_JAIL)
188 match = (u->xid == (uid_t)insn->d[0]);
189 else if (insn->o.opcode == O_GID)
190 match = (u->gid == (uid_t)insn->d[0]);
193 #endif /* __linux__ */
196 jailed(struct ucred *cred)
202 * Return 1 if an internet address is for a ``local'' host
203 * (one to which we have a connection). If subnetsarelocal
204 * is true, this includes other subnets of the local net.
205 * Otherwise, it includes only the directly-connected (sub)nets.
208 in_localaddr(struct in_addr in)
214 sooptcopyout(struct sockopt *sopt, const void *buf, size_t len)
216 size_t valsize = sopt->sopt_valsize;
219 sopt->sopt_valsize = valsize = len;
220 //printf("copyout buf = %p, sopt = %p, soptval = %p, len = %d \n", buf, sopt, sopt->sopt_val, len);
221 bcopy(buf, sopt->sopt_val, valsize);
226 * copy data from userland to kernel
229 sooptcopyin(struct sockopt *sopt, void *buf, size_t len, size_t minlen)
231 size_t valsize = sopt->sopt_valsize;
233 if (valsize < minlen)
236 sopt->sopt_valsize = valsize = len;
237 //printf("copyin buf = %p, sopt = %p, soptval = %p, len = %d \n", buf, sopt, sopt->sopt_val, len);
238 bcopy(sopt->sopt_val, buf, valsize);
243 getmicrouptime(struct timeval *tv)
249 #include <arpa/inet.h>
252 inet_ntoa_r(struct in_addr ina, char *buf)
256 unsigned char *ucp = (unsigned char *)&ina;
258 sprintf(buf, "%d.%d.%d.%d",
268 inet_ntoa(struct in_addr ina)
271 return inet_ntoa_r(ina, buf);
278 static unsigned long seed;
281 KeQuerySystemTime(&tm);
284 return RtlRandomEx(&seed) & 0x7fffffff;
287 get_random_bytes(&r, sizeof(r));
288 return r & 0x7fffffff;
294 * do_div really does a u64 / u32 bit division.
295 * we save the sign and convert to uint befor calling.
296 * We are safe just because we always call it with small operands.
299 div64(int64_t a, int64_t b)
306 int sign = ((a>0)?1:-1) * ((b>0)?1:-1);
317 strlcpy(char *dst, const char *src, size_t siz)
323 /* Copy as many bytes as will fit */
324 if (n != 0 && --n != 0) {
326 if ((*d++ = *s++) == 0)
331 /* Not enough room in dst, add NUL and traverse rest of src */
334 *d = '\0'; /* NUL-terminate dst */
339 return(s - src - 1); /* count does not include NUL */
344 * compact version of fnmatch.
347 fnmatch(const char *pattern, const char *string, int flags)
351 if (!string || !pattern)
352 return 1; /* no match */
353 while ( (s = *string++) ) {
355 if (p == '\0') /* pattern is over, no match */
357 if (p == '*') /* wildcard, match */
359 if (p == '.' || p == s) /* char match, continue */
361 return 1; /* no match */
363 /* end of string, make sure the pattern is over too */
364 if (*pattern == '\0' || *pattern == '*')
366 return 1; /* no match */
371 * linux 2.6.33 defines these functions to access to
372 * skbuff internal structures. Define the missing
373 * function for the previous versions too.
376 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
377 inline void skb_dst_set(struct sk_buff *skb, struct dst_entry *dst)
382 inline struct dst_entry *skb_dst(const struct sk_buff *skb)
384 return (struct dst_entry *)skb->dst;
386 #endif /* < 2.6.31 */
390 /* support for sysctl emulation.
391 * XXX this is actually MI code that should be enabled also on openwrt
393 #ifdef EMULATE_SYSCTL
394 static struct sysctltable GST;
397 kesysctl_emu_get(struct sockopt* sopt)
399 struct dn_id* oid = sopt->sopt_val;
400 struct sysctlhead* entry;
401 int sizeneeded = sizeof(struct dn_id) + GST.totalsize +
402 sizeof(struct sysctlhead);
403 unsigned char* pstring;
404 unsigned char* pdata;
407 if (sopt->sopt_valsize < sizeneeded) {
408 // this is a probe to retrieve the space needed for
409 // a dump of the sysctl table
410 oid->id = sizeneeded;
411 sopt->sopt_valsize = sizeof(struct dn_id);
415 entry = (struct sysctlhead*)(oid+1);
416 for( i=0; i<GST.count; i++) {
417 entry->blocklen = GST.entry[i].head.blocklen;
418 entry->namelen = GST.entry[i].head.namelen;
419 entry->flags = GST.entry[i].head.flags;
420 entry->datalen = GST.entry[i].head.datalen;
421 pdata = (unsigned char*)(entry+1);
422 pstring = pdata+GST.entry[i].head.datalen;
423 bcopy(GST.entry[i].data, pdata, GST.entry[i].head.datalen);
424 bcopy(GST.entry[i].name, pstring, GST.entry[i].head.namelen);
425 entry = (struct sysctlhead*)
426 ((unsigned char*)(entry) + GST.entry[i].head.blocklen);
428 sopt->sopt_valsize = sizeneeded;
433 kesysctl_emu_set(void* p, int l)
435 struct sysctlhead* entry;
436 unsigned char* pdata;
437 unsigned char* pstring;
440 entry = (struct sysctlhead*)(((struct dn_id*)p)+1);
441 pdata = (unsigned char*)(entry+1);
442 pstring = pdata + entry->datalen;
444 for (i=0; i<GST.count; i++) {
445 if (strcmp(GST.entry[i].name, pstring) != 0)
447 printf("%s: match found! %s\n",__FUNCTION__,pstring);
448 //sanity check on len, not really useful now since
449 //we only accept int32
450 if (entry->datalen != GST.entry[i].head.datalen) {
451 printf("%s: len mismatch, user %d vs kernel %d\n",
452 __FUNCTION__, entry->datalen,
453 GST.entry[i].head.datalen);
456 // check access (at the moment flags handles only the R/W rights
457 //later on will be type + access
458 if( (GST.entry[i].head.flags & 3) == CTLFLAG_RD) {
459 printf("%s: the entry %s is read only\n",
460 __FUNCTION__,GST.entry[i].name);
463 bcopy(pdata, GST.entry[i].data, GST.entry[i].head.datalen);
466 printf("%s: match not found\n",__FUNCTION__);
470 /* convert all _ to . until the first . */
472 underscoretopoint(char* s)
474 for (; *s && *s != '.'; s++)
486 for (i=0; i<GST.count; i++)
487 size += GST.entry[i].head.namelen;
488 GST.namebuffer = malloc(size, 0, 0);
489 if (GST.namebuffer == NULL)
491 name = GST.namebuffer;
492 for (i=0; i<GST.count; i++) {
493 bcopy(GST.entry[i].name, name, GST.entry[i].head.namelen);
494 underscoretopoint(name);
495 GST.entry[i].name = name;
496 name += GST.entry[i].head.namelen;
506 for (i=0; i<GST.count; i++) {
507 printf("SYSCTL: entry %i\n", i);
508 printf("name %s\n", GST.entry[i].name);
509 printf("namelen %i\n", GST.entry[i].head.namelen);
510 printf("type %i access %i\n",
511 GST.entry[i].head.flags >> 2,
512 GST.entry[i].head.flags & 0x00000003);
513 printf("data %i\n", *(int*)(GST.entry[i].data));
514 printf("datalen %i\n", GST.entry[i].head.datalen);
515 printf("blocklen %i\n", GST.entry[i].head.blocklen);
519 void sysctl_addgroup_f1();
520 void sysctl_addgroup_f2();
521 void sysctl_addgroup_f3();
522 void sysctl_addgroup_f4();
529 sysctl_addgroup_f1();
530 sysctl_addgroup_f2();
531 sysctl_addgroup_f3();
532 sysctl_addgroup_f4();
535 printf("conversion of names failed for some reason\n");
537 printf("*** Global Sysctl Table entries = %i, total size = %i ***\n",
538 GST.count, GST.totalsize);
544 if (GST.namebuffer != NULL)
545 free(GST.namebuffer,0);
546 bzero(&GST, sizeof(GST));
550 sysctl_pushback(char* name, int flags, int datalen, void* data)
552 if (GST.count >= GST_HARD_LIMIT) {
553 printf("WARNING: global sysctl table full, this entry will not be added,"
554 "please recompile the module increasing the table size\n");
557 GST.entry[GST.count].head.namelen = strlen(name)+1; //add space for '\0'
558 GST.entry[GST.count].name = name;
559 GST.entry[GST.count].head.flags = flags;
560 GST.entry[GST.count].data = data;
561 GST.entry[GST.count].head.datalen = datalen;
562 GST.entry[GST.count].head.blocklen =
563 ((sizeof(struct sysctlhead) + GST.entry[GST.count].head.namelen +
564 GST.entry[GST.count].head.datalen)+3) & ~3;
565 GST.totalsize += GST.entry[GST.count].head.blocklen;
568 #endif /* EMULATE_SYSCTL */