/* * Send NDP Router Advertisement */ void ndp_send_ra(Slirp *slirp) { DEBUG_CALL("ndp_send_ra"); /* Build IPv6 packet */ struct mbuf *t = m_get(slirp); struct ip6 *rip = mtod(t, struct ip6 *); rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; rip->ip_nh = IPPROTO_ICMPV6; rip->ip_pl = htons(ICMP6_NDP_RA_MINLEN + NDPOPT_LINKLAYER_LEN + NDPOPT_PREFIXINFO_LEN); t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); /* Build ICMPv6 packet */ t->m_data += sizeof(struct ip6); struct icmp6 *ricmp = mtod(t, struct icmp6 *); ricmp->icmp6_type = ICMP6_NDP_RA; ricmp->icmp6_code = 0; ricmp->icmp6_cksum = 0; /* NDP */ ricmp->icmp6_nra.chl = NDP_AdvCurHopLimit; ricmp->icmp6_nra.M = NDP_AdvManagedFlag; ricmp->icmp6_nra.O = NDP_AdvOtherConfigFlag; ricmp->icmp6_nra.reserved = 0; ricmp->icmp6_nra.lifetime = htons(NDP_AdvDefaultLifetime); ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime); ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime); /* Source link-layer address (NDP option) */ t->m_data += ICMP6_NDP_RA_MINLEN; struct ndpopt *opt = mtod(t, struct ndpopt *); opt->ndpopt_type = NDPOPT_LINKLAYER_SOURCE; opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer); /* Prefix information (NDP option) */ t->m_data += NDPOPT_LINKLAYER_LEN; struct ndpopt *opt2 = mtod(t, struct ndpopt *); opt2->ndpopt_type = NDPOPT_PREFIX_INFO; opt2->ndpopt_len = NDPOPT_PREFIXINFO_LEN / 8; opt2->ndpopt_prefixinfo.prefix_length = slirp->vprefix_len; opt2->ndpopt_prefixinfo.L = 1; opt2->ndpopt_prefixinfo.A = 1; opt2->ndpopt_prefixinfo.reserved1 = 0; opt2->ndpopt_prefixinfo.valid_lt = htonl(NDP_AdvValidLifetime); opt2->ndpopt_prefixinfo.pref_lt = htonl(NDP_AdvPrefLifetime); opt2->ndpopt_prefixinfo.reserved2 = 0; opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6; /* ICMPv6 Checksum */ t->m_data -= NDPOPT_LINKLAYER_LEN; t->m_data -= ICMP6_NDP_RA_MINLEN; t->m_data -= sizeof(struct ip6); ricmp->icmp6_cksum = ip6_cksum(t); ip6_output(NULL, t, 0); }
/* * Get urgent data * * When the socket is created, we set it SO_OOBINLINE, * so when OOB data arrives, we soread() it and everything * in the send buffer is sent as urgent data */ int sorecvoob(struct socket *so) { struct tcpcb *tp = sototcpcb(so); int ret; DEBUG_CALL("sorecvoob"); DEBUG_ARG("so = %p", so); /* * We take a guess at how much urgent data has arrived. * In most situations, when urgent data arrives, the next * read() should get all the urgent data. This guess will * be wrong however if more data arrives just after the * urgent data, or the read() doesn't return all the * urgent data. */ ret = soread(so); if (ret > 0) { tp->snd_up = tp->snd_una + so->so_snd.sb_cc; tp->t_force = 1; tcp_output(tp); tp->t_force = 0; } return ret; }
static int mount_local_read (const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { char *r; size_t rsize; const size_t limit = 2 * 1024 * 1024; DECL_G (); DEBUG_CALL ("%s, %p, %zu, %ld", path, buf, size, (long) offset); /* The guestfs protocol limits size to somewhere over 2MB. We just * reduce the requested size here accordingly and push the problem * up to every user. http://www.jwz.org/doc/worse-is-better.html */ if (size > limit) size = limit; r = guestfs_pread (g, path, size, offset, &rsize); if (r == NULL) RETURN_ERRNO; /* This should never happen, but at least it stops us overflowing * the output buffer if it does happen. */ if (rsize > size) rsize = size; memcpy (buf, r, rsize); free (r); return rsize; }
static int mount_local_statfs (const char *path, struct statvfs *stbuf) { CLEANUP_FREE_STATVFS struct guestfs_statvfs *r; DECL_G (); DEBUG_CALL ("%s, %p", path, stbuf); r = guestfs_statvfs (g, path); if (r == NULL) RETURN_ERRNO; stbuf->f_bsize = r->bsize; stbuf->f_frsize = r->frsize; stbuf->f_blocks = r->blocks; stbuf->f_bfree = r->bfree; stbuf->f_bavail = r->bavail; stbuf->f_files = r->files; stbuf->f_ffree = r->ffree; stbuf->f_favail = r->favail; stbuf->f_fsid = r->fsid; stbuf->f_flag = r->flag; stbuf->f_namemax = r->namemax; return 0; }
/* Nautilus loves to use access(2) to test everything about a file, * such as whether it's executable. Therefore treat this a lot like * mount_local_getattr. */ static int mount_local_access (const char *path, int mask) { struct stat statbuf; int r; struct fuse_context *fuse; int ok = 1; DECL_G (); DEBUG_CALL ("%s, %d", path, mask); if (g->ml_read_only && (mask & W_OK)) return -EROFS; r = mount_local_getattr (path, &statbuf); if (r < 0 || mask == F_OK) { debug (g, "%s: mount_local_getattr returned r = %d", path, r); return r; } fuse = fuse_get_context (); /* Root user should be able to access everything, so only bother * with these fine-grained tests for non-root. (RHBZ#1106548). */ if (fuse->uid != 0) { if (mask & R_OK) ok = ok && ( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IRUSR : fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IRGRP : statbuf.st_mode & S_IROTH); if (mask & W_OK) ok = ok && ( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IWUSR : fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IWGRP : statbuf.st_mode & S_IWOTH); if (mask & X_OK) ok = ok && ( fuse->uid == statbuf.st_uid ? statbuf.st_mode & S_IXUSR : fuse->gid == statbuf.st_gid ? statbuf.st_mode & S_IXGRP : statbuf.st_mode & S_IXOTH); } debug (g, "%s: " "testing access mask%s%s%s%s: " "caller UID:GID = %ju:%ju, " "file UID:GID = %ju:%ju, " "file mode = %o, " "result = %s", path, mask & R_OK ? " R_OK" : "", mask & W_OK ? " W_OK" : "", mask & X_OK ? " X_OK" : "", mask == 0 ? " 0" : "", (uintmax_t) fuse->uid, (uintmax_t) fuse->gid, (uintmax_t) statbuf.st_uid, (uintmax_t) statbuf.st_gid, statbuf.st_mode, ok ? "OK" : "EACCESS"); return ok ? 0 : -EACCES; }
static int mount_local_readlink (const char *path, char *buf, size_t size) { const char *r; int free_it = 0; size_t len; DECL_G (); DEBUG_CALL ("%s, %p, %zu", path, buf, size); r = rlc_lookup (g, path); if (!r) { r = guestfs_readlink (g, path); if (r == NULL) RETURN_ERRNO; free_it = 1; } /* Note this is different from the real readlink(2) syscall. FUSE wants * the string to be always nul-terminated, even if truncated. */ len = strlen (r); if (len > size - 1) len = size - 1; memcpy (buf, r, len); buf[len] = '\0'; if (free_it) { char *tmp = (char *) r; free (tmp); } return 0; }
void m_free(struct mbuf *m) { DEBUG_CALL("m_free"); DEBUG_ARG("m = %lx", (long )m); if(m) { /* Remove from m_usedlist */ if (m->m_flags & M_USEDLIST) remque(m); /* If it's M_EXT, free() it */ if (m->m_flags & M_EXT) free(m->m_ext); /* * Either free() it or put it on the free list */ if (m->m_flags & M_DOFREE) { m->slirp->mbuf_alloced--; free(m); } else if ((m->m_flags & M_FREELIST) == 0) { insque(m,&m->slirp->m_freelist); m->m_flags = M_FREELIST; /* Clobber other flags */ } } /* if(m) */ }
void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; DEBUG_CALL("tcp_respond"); DEBUG_ARG("tp = %lx", (long)tp); DEBUG_ARG("ti = %lx", (long)ti); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("ack = %u", ack); DEBUG_ARG("seq = %u", seq); DEBUG_ARG("flags = %x", flags); if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == NULL) { if ((m = m_get()) == NULL) return; #ifdef TCP_COMPAT_42 tlen = 1; #else tlen = 0; #endif m->m_data += IF_MAXLINKHDR; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else {
/* * Read from so's socket into sb_snd, updating all relevant sbuf fields * NOTE: This will only be called if it is select()ed for reading, so * a read() of 0 (or less) means it's disconnected */ int soread(struct socket *so) { int n, nn; struct sbuf *sb = &so->so_snd; struct iovec iov[2]; DEBUG_CALL("soread"); DEBUG_ARG("so = %p", so); /* * No need to check if there's enough room to read. * soread wouldn't have been called if there weren't */ sopreprbuf(so, iov, &n); #ifdef HAVE_READV nn = readv(so->s, (struct iovec *)iov, n); DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); #else nn = qemu_recv(so->s, iov[0].iov_base, iov[0].iov_len,0); #endif if (nn <= 0) { if (nn < 0 && (errno == EINTR || errno == EAGAIN)) return 0; else { DEBUG_MISC((dfd, " --- soread() disconnected, nn = %d, errno = %d-%s\n", nn, errno,strerror(errno))); sofcantrcvmore(so); tcp_sockclosed(sototcpcb(so)); return -1; } } #ifndef HAVE_READV /* * If there was no error, try and read the second time round * We read again if n = 2 (ie, there's another part of the buffer) * and we read as much as we could in the first read * We don't test for <= 0 this time, because there legitimately * might not be any more data (since the socket is non-blocking), * a close will be detected on next iteration. * A return of -1 wont (shouldn't) happen, since it didn't happen above */ if (n == 2 && nn == iov[0].iov_len) { int ret; ret = qemu_recv(so->s, iov[1].iov_base, iov[1].iov_len,0); if (ret > 0) nn += ret; } DEBUG_MISC((dfd, " ... read nn = %d bytes\n", nn)); #endif /* Update fields */ sb->sb_cc += nn; sb->sb_wptr += nn; if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen)) sb->sb_wptr -= sb->sb_datalen; return nn; }
/* * Send a single message to the TCP at address specified by * the given TCP/IP header. If m == 0, then we make a copy * of the tcpiphdr at ti and send directly to the addressed host. * This is used to force keep alive messages out using the TCP * template for a connection tp->t_template. If flags are given * then we send a message back to the TCP which originated the * segment ti, and discard the mbuf containing it and any other * attached mbufs. * * In any case the ack and sequence number of the transmitted * segment are as specified by the parameters. */ void tcp_respond(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags) { register int tlen; int win = 0; DEBUG_CALL("tcp_respond"); DEBUG_ARG("tp = %p", tp); DEBUG_ARG("ti = %p", ti); DEBUG_ARG("m = %p", m); DEBUG_ARG("ack = %u", ack); DEBUG_ARG("seq = %u", seq); DEBUG_ARG("flags = %x", flags); if (tp) win = sbspace(&tp->t_socket->so_rcv); if (m == NULL) { if (!tp || (m = m_get(tp->t_socket->slirp)) == NULL) return; tlen = 0; m->m_data += IF_MAXLINKHDR; *mtod(m, struct tcpiphdr *) = *ti; ti = mtod(m, struct tcpiphdr *); flags = TH_ACK; } else {
size_t sopreprbuf(struct socket *so, struct iovec *iov, int *np) { int n, lss, total; struct sbuf *sb = &so->so_snd; int len = sb->sb_datalen - sb->sb_cc; int mss = so->so_tcpcb->t_maxseg; DEBUG_CALL("sopreprbuf"); DEBUG_ARG("so = %lx", (long )so); len = sb->sb_datalen - sb->sb_cc; if (len <= 0) return 0; iov[0].iov_base = sb->sb_wptr; iov[1].iov_base = NULL; iov[1].iov_len = 0; if (sb->sb_wptr < sb->sb_rptr) { iov[0].iov_len = sb->sb_rptr - sb->sb_wptr; /* Should never succeed, but... */ if (iov[0].iov_len > len) iov[0].iov_len = len; if (iov[0].iov_len > mss) iov[0].iov_len -= iov[0].iov_len%mss; n = 1; } else { iov[0].iov_len = (sb->sb_data + sb->sb_datalen) - sb->sb_wptr; /* Should never succeed, but... */ if (iov[0].iov_len > len) iov[0].iov_len = len; len -= iov[0].iov_len; if (len) { iov[1].iov_base = sb->sb_data; iov[1].iov_len = sb->sb_rptr - sb->sb_data; if(iov[1].iov_len > len) iov[1].iov_len = len; total = iov[0].iov_len + iov[1].iov_len; if (total > mss) { lss = total%mss; if (iov[1].iov_len > lss) { iov[1].iov_len -= lss; n = 2; } else { lss -= iov[1].iov_len; iov[0].iov_len -= lss; n = 1; } } else n = 2; } else { if (iov[0].iov_len > mss) iov[0].iov_len -= iov[0].iov_len%mss; n = 1; } } if (np) *np = n; return iov[0].iov_len + (n - 1) * iov[1].iov_len; }
static int lpx_USER_attach( struct socket *so, int proto, struct proc *td ) { int error; int s; struct lpxpcb *lpxp = sotolpxpcb(so); if (lpxp != NULL) return (EINVAL); s = splnet(); error = Lpx_PCB_alloc(so, &lpxpcb, td); splx(s); if (error == 0) { int lpxsends, lpxrecvs; lpxsends = 256 * 1024; lpxrecvs = 256 * 1024; while(lpxsends > 0 && lpxrecvs > 0) { error = soreserve(so, lpxsends, lpxrecvs); if(error == 0) break; lpxsends -= (1024*2); lpxrecvs -= (1024*2); } DEBUG_CALL(4, ("lpxsends = %d\n", lpxsends/1024)); // error = soreserve(so, lpxsendspace, lpxrecvspace); } return (error); }
struct mbuf * m_get(void) { register struct mbuf *m; int flags = 0; DEBUG_CALL("m_get"); if (m_freelist.m_next == &m_freelist) { m = (struct mbuf *)malloc(SLIRP_MSIZE); if (m == NULL) goto end_error; mbuf_alloced++; if (mbuf_alloced > MBUF_THRESH) flags = M_DOFREE; if (mbuf_alloced > mbuf_max) mbuf_max = mbuf_alloced; } else { m = m_freelist.m_next; remque(m); } insque(m,&m_usedlist); m->m_flags = (flags | M_USEDLIST); m->m_size = SLIRP_MSIZE - sizeof(struct m_hdr); m->m_data = m->m_dat; m->m_len = 0; m->m_nextpkt = NULL; m->m_prevpkt = NULL; end_error: DEBUG_ARG("m = %lx", (long )m); return m; }
/* Ditto as above. */ static int mount_local_listxattr (const char *path, char *list, size_t size) { DECL_G (); DEBUG_CALL ("%s, %p, %zu", path, list, size); const struct guestfs_xattr_list *xattrs; int free_attrs = 0; xattrs = xac_lookup (g, path); if (xattrs == NULL) { xattrs = guestfs_lgetxattrs (g, path); if (xattrs == NULL) RETURN_ERRNO; free_attrs = 1; } /* Calculate how much space is required to hold the result. */ size_t space = 0; size_t len; size_t i; for (i = 0; i < xattrs->len; ++i) { len = strlen (xattrs->val[i].attrname) + 1; space += len; } /* The listxattr man page is unclear, but if list == NULL then we * return the space required (the caller then makes a second syscall * after allocating the required amount of space). If list != NULL * then it's not clear what we should do, but it appears we should * copy as much as possible and return -ERANGE if there's not enough * space in the buffer. */ ssize_t r; if (list == NULL) { r = space; goto out; } r = 0; for (i = 0; i < xattrs->len; ++i) { len = strlen (xattrs->val[i].attrname) + 1; if (size >= len) { memcpy (list, xattrs->val[i].attrname, len); size -= len; list += len; r += len; } else { r = -ERANGE; break; } } out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); return r; }
int udp_output2_(struct socket *so, struct mbuf *m, const SockAddress* saddr, const SockAddress* daddr, int iptos) { register struct udpiphdr *ui; uint32_t saddr_ip = sock_address_get_ip(saddr); uint32_t daddr_ip = sock_address_get_ip(daddr); int saddr_port = sock_address_get_port(saddr); int daddr_port = sock_address_get_port(daddr); int error = 0; DEBUG_CALL("udp_output"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("saddr = %lx", (long) saddr_ip); DEBUG_ARG("daddr = %lx", (long) daddr_ip); /* * Adjust for header */ m->m_data -= sizeof(struct udpiphdr); m->m_len += sizeof(struct udpiphdr); /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); memset(&ui->ui_i.ih_mbuf, 0 , sizeof(struct mbuf_ptr)); ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ ui->ui_src = ip_seth(saddr_ip); ui->ui_dst = ip_seth(daddr_ip); ui->ui_sport = port_seth(saddr_port); ui->ui_dport = port_seth(daddr_port); ui->ui_ulen = ui->ui_len; /* * Stuff checksum and output datagram. */ ui->ui_sum = 0; if (UDPCKSUM) { if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) ui->ui_sum = 0xffff; } ((struct ip *)ui)->ip_len = m->m_len; ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; STAT(udpstat.udps_opackets++); error = ip_output(so, m); return (error); }
/* The guestfs(3) API for getting xattrs is much easier to use * than the real syscall. Unfortunately we now have to emulate * the real syscall using that API :-( */ static int mount_local_getxattr (const char *path, const char *name, char *value, size_t size) { DECL_G (); DEBUG_CALL ("%s, %s, %p, %zu", path, name, value, size); const struct guestfs_xattr_list *xattrs; int free_attrs = 0; xattrs = xac_lookup (g, path); if (xattrs == NULL) { xattrs = guestfs_lgetxattrs (g, path); if (xattrs == NULL) RETURN_ERRNO; free_attrs = 1; } /* Find the matching attribute (index in 'i'). */ ssize_t r; size_t i; for (i = 0; i < xattrs->len; ++i) { if (STREQ (xattrs->val[i].attrname, name)) break; } if (i == xattrs->len) { /* not found */ r = -ENOATTR; goto out; } /* The getxattr man page is unclear, but if value == NULL then we * return the space required (the caller then makes a second syscall * after allocating the required amount of space). If value != NULL * then it's not clear what we should do, but it appears we should * copy as much as possible and return -ERANGE if there's not enough * space in the buffer. */ size_t sz = xattrs->val[i].attrval_len; if (value == NULL) { r = sz; goto out; } if (sz <= size) r = sz; else { r = -ERANGE; sz = size; } memcpy (value, xattrs->val[i].attrval, sz); out: if (free_attrs) guestfs_free_xattr_list ((struct guestfs_xattr_list *) xattrs); return r; }
/* * Put an ip fragment on a reassembly chain. * Like insque, but pointers in middle of structure. */ void ip_enq(struct ipasfrag *p, struct ipasfrag *prev) { DEBUG_CALL("ip_enq"); DEBUG_ARG("prev = %lx", (long)prev); p->ipf_prev = (ipasfragp_32) prev; p->ipf_next = prev->ipf_next; ((struct ipasfrag *)(prev->ipf_next))->ipf_prev = (ipasfragp_32) p; prev->ipf_next = (ipasfragp_32) p; }
void arp_table_add(Slirp *slirp, uint32_t ip_addr, uint8_t ethaddr[ETH_ALEN]) { const uint32_t broadcast_addr = ~slirp->vnetwork_mask.s_addr | slirp->vnetwork_addr.s_addr; ArpTable *arptbl = &slirp->arp_table; int i; DEBUG_CALL("arp_table_add"); DEBUG_ARG("ip = %s", inet_ntoa((struct in_addr){.s_addr = ip_addr}));
/* * Process a received ICMPv6 message. */ void icmp6_input(struct mbuf *m) { struct icmp6 *icmp; struct ip6 *ip = mtod(m, struct ip6 *); Slirp *slirp = m->slirp; int hlen = sizeof(struct ip6); DEBUG_CALL("icmp6_input"); DEBUG_ARG("m = %lx", (long) m); DEBUG_ARG("m_len = %d", m->m_len); if (ntohs(ip->ip_pl) < ICMP6_MINLEN) { goto end; } if (ip6_cksum(m)) { goto end; } m->m_len -= hlen; m->m_data += hlen; icmp = mtod(m, struct icmp6 *); m->m_len += hlen; m->m_data -= hlen; DEBUG_ARG("icmp6_type = %d", icmp->icmp6_type); switch (icmp->icmp6_type) { case ICMP6_ECHO_REQUEST: if (in6_equal_host(&ip->ip_dst)) { icmp6_send_echoreply(m, slirp, ip, icmp); } else { /* TODO */ error_report("external icmpv6 not supported yet"); } break; case ICMP6_NDP_RS: case ICMP6_NDP_RA: case ICMP6_NDP_NS: case ICMP6_NDP_NA: case ICMP6_NDP_REDIRECT: ndp_input(m, slirp, ip, icmp); break; case ICMP6_UNREACH: case ICMP6_TOOBIG: case ICMP6_TIMXCEED: case ICMP6_PARAMPROB: /* XXX? report error? close socket? */ default: break; } end: m_free(m); }
/**************************************************************************** NAME aghfpCallCloseComplete DESCRIPTION A call closure has been completed. */ void aghfpCallCloseComplete (void) { DEBUG_CALL(("aghfpCallCloseComplete app_state=%x\n", the_app->app_state)); switch ( the_app->app_state ) { case AppStateInCall: { setAppState(AppStateIdle); if ( the_app->comm_action != CommActionCall ) kickCommAction(the_app->comm_action); break; } default: { DEBUG_CALL((" - IGNORED\n")); break; } } }
/* * XXX This should really be tcp_listen */ struct socket * solisten(u_int port, u_int32_t laddr, u_int lport, int flags) { SockAddress addr; uint32_t addr_ip; struct socket *so; int s; DEBUG_CALL("solisten"); DEBUG_ARG("port = %d", port); DEBUG_ARG("laddr = %x", laddr); DEBUG_ARG("lport = %d", lport); DEBUG_ARG("flags = %x", flags); if ((so = socreate()) == NULL) { /* free(so); Not sofree() ??? free(NULL) == NOP */ return NULL; } /* Don't tcp_attach... we don't need so_snd nor so_rcv */ if ((so->so_tcpcb = tcp_newtcpcb(so)) == NULL) { free(so); return NULL; } insque(so,&tcb); /* * SS_FACCEPTONCE sockets must time out. */ if (flags & SS_FACCEPTONCE) so->so_tcpcb->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT*2; so->so_state = (SS_FACCEPTCONN|flags); so->so_laddr_port = lport; /* Kept in host format */ so->so_laddr_ip = laddr; /* Ditto */ so->so_haddr_port = port; s = socket_loopback_server( port, SOCKET_STREAM ); if (s < 0) return NULL; socket_get_address(s, &addr); so->so_faddr_port = sock_address_get_port(&addr); addr_ip = (uint32_t) sock_address_get_ip(&addr); if (addr_ip == 0 || addr_ip == loopback_addr_ip) so->so_faddr_ip = alias_addr_ip; else so->so_faddr_ip = addr_ip; so->s = s; return so; }
/* * Try and write() to the socket, whatever doesn't get written * append to the buffer... for a host with a fast net connection, * this prevents an unnecessary copy of the data * (the socket is non-blocking, so we won't hang) */ void sbappend(struct socket *so, struct mbuf *m) { int ret = 0; DEBUG_CALL("sbappend"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("m->m_len = %d", m->m_len); /* Shouldn't happen, but... e.g. foreign host closes connection */ if (m->m_len <= 0) { m_free(m); return; } /* * If there is urgent data, call sosendoob * if not all was sent, sowrite will take care of the rest * (The rest of this function is just an optimisation) */ if (so->so_urgc) { sbappendsb(&so->so_rcv, m); m_free(m); sosendoob(so); return; } /* * We only write if there's nothing in the buffer, * ottherwise it'll arrive out of order, and hence corrupt */ if (!so->so_rcv.sb_cc) ret = send(so->s, m->m_data, m->m_len, 0); if (ret <= 0) { /* * Nothing was written * It's possible that the socket has closed, but * we don't need to check because if it has closed, * it will be detected in the normal way by soread() */ sbappendsb(&so->so_rcv, m); } else if (ret != m->m_len) { /* * Something was written, but not everything.. * sbappendsb the rest */ m->m_len -= ret; m->m_data += ret; sbappendsb(&so->so_rcv, m); } /* else */ /* Whatever happened, we free the mbuf */ m_free(m); }
int udp_output2(struct socket *so, struct mbuf *m, struct sockaddr_in *saddr, struct sockaddr_in *daddr, int iptos) { register struct udpiphdr *ui; int error = 0; DEBUG_CALL("udp_output"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("m = %lx", (long)m); DEBUG_ARG("saddr = %lx", (long)saddr->sin_addr.s_addr); DEBUG_ARG("daddr = %lx", (long)daddr->sin_addr.s_addr); /* * Adjust for header */ m->m_data -= sizeof(struct udpiphdr); m->m_len += sizeof(struct udpiphdr); /* * Fill in mbuf with extended UDP header * and addresses and length put into network format. */ ui = mtod(m, struct udpiphdr *); ui->ui_next = ui->ui_prev = 0; ui->ui_x1 = 0; ui->ui_pr = IPPROTO_UDP; ui->ui_len = htons(m->m_len - sizeof(struct ip)); /* + sizeof (struct udphdr)); */ /* XXXXX Check for from-one-location sockets, or from-any-location sockets */ ui->ui_src = saddr->sin_addr; ui->ui_dst = daddr->sin_addr; ui->ui_sport = saddr->sin_port; ui->ui_dport = daddr->sin_port; ui->ui_ulen = ui->ui_len; /* * Stuff checksum and output datagram. */ ui->ui_sum = 0; if (UDPCKSUM) { if ((ui->ui_sum = cksum(m, /* sizeof (struct udpiphdr) + */ m->m_len)) == 0) ui->ui_sum = 0xffff; } ((struct ip *)ui)->ip_len = m->m_len; ((struct ip *)ui)->ip_ttl = IPDEFTTL; ((struct ip *)ui)->ip_tos = iptos; STAT(udpstat.udps_opackets++); error = ip_output(so, m); return (error); }
static int mount_local_release (const char *path, struct fuse_file_info *fi) { DECL_G (); DEBUG_CALL ("%s", path); /* Just a stub. This method is optional and can safely be left * unimplemented. */ return 0; }
void Game::draw() { SDL_RenderClear( gSDLConfig::instance().getRenderer() ); DEBUG_ASSERT( m_sceneManagerPtr->getCurrentScenePtr() != NULL ) m_sceneManagerPtr->draw(); DEBUG_CALL(drawAvgFps()); SDL_RenderPresent( gSDLConfig::instance().getRenderer() ); }
bool ndp_table_search(Slirp *slirp, struct in6_addr ip_addr, uint8_t out_ethaddr[ETH_ALEN]) { NdpTable *ndp_table = &slirp->ndp_table; int i; DEBUG_CALL("ndp_table_search"); #if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600) char addrstr[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); DEBUG_ARG("ip = %s", addrstr); #endif assert(!IN6_IS_ADDR_UNSPECIFIED(&ip_addr)); /* Multicast address: fec0::abcd:efgh/8 -> 33:33:ab:cd:ef:gh */ if (IN6_IS_ADDR_MULTICAST(&ip_addr)) { out_ethaddr[0] = 0x33; out_ethaddr[1] = 0x33; out_ethaddr[2] = ip_addr.s6_addr[12]; out_ethaddr[3] = ip_addr.s6_addr[13]; out_ethaddr[4] = ip_addr.s6_addr[14]; out_ethaddr[5] = ip_addr.s6_addr[15]; DEBUG_ARGS((dfd, " multicast addr = %02x:%02x:%02x:%02x:%02x:%02x\n", out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); return 1; } for (i = 0; i < NDP_TABLE_SIZE; i++) { if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { memcpy(out_ethaddr, ndp_table->table[i].eth_addr, ETH_ALEN); DEBUG_ARGS((dfd, " found hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", out_ethaddr[0], out_ethaddr[1], out_ethaddr[2], out_ethaddr[3], out_ethaddr[4], out_ethaddr[5])); return 1; } } DEBUG_CALL(" ip not found in table"); return 0; }
/* * Send urgent data * There's a lot duplicated code here, but... */ int sosendoob(struct socket *so) { struct sbuf *sb = &so->so_rcv; char buff[2048]; /* XXX Shouldn't be sending more oob data than this */ int n, len; DEBUG_CALL("sosendoob"); DEBUG_ARG("so = %lx", (long)so); DEBUG_ARG("sb->sb_cc = %d", sb->sb_cc); if (so->so_urgc > 2048) so->so_urgc = 2048; /* XXXX */ if (sb->sb_rptr < sb->sb_wptr) { /* We can send it directly */ n = slirp_send(so, sb->sb_rptr, so->so_urgc, (MSG_OOB)); /* |MSG_DONTWAIT)); */ so->so_urgc -= n; DEBUG_MISC((dfd, " --- sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); } else { /* * Since there's no sendv or sendtov like writev, * we must copy all data to a linear buffer then * send it all */ len = (sb->sb_data + sb->sb_datalen) - sb->sb_rptr; if (len > so->so_urgc) len = so->so_urgc; memcpy(buff, sb->sb_rptr, len); so->so_urgc -= len; if (so->so_urgc) { n = sb->sb_wptr - sb->sb_data; if (n > so->so_urgc) n = so->so_urgc; memcpy((buff + len), sb->sb_data, n); so->so_urgc -= n; len += n; } n = slirp_send(so, buff, len, (MSG_OOB)); /* |MSG_DONTWAIT)); */ #ifdef DEBUG if (n != len) DEBUG_ERROR((dfd, "Didn't send all data urgently XXXXX\n")); #endif DEBUG_MISC((dfd, " ---2 sent %d bytes urgent data, %d urgent bytes left\n", n, so->so_urgc)); } sb->sb_cc -= n; sb->sb_rptr += n; if (sb->sb_rptr >= (sb->sb_data + sb->sb_datalen)) sb->sb_rptr -= sb->sb_datalen; return n; }
/* All this function needs to do is to check that the requested open * flags are valid. See the notes in <fuse/fuse.h>. */ static int mount_local_open (const char *path, struct fuse_file_info *fi) { const int flags = fi->flags & O_ACCMODE; DECL_G (); DEBUG_CALL ("%s, 0%o", path, (unsigned) fi->flags); if (g->ml_read_only && flags != O_RDONLY) return -EROFS; return 0; }
void ndp_table_add(Slirp *slirp, struct in6_addr ip_addr, uint8_t ethaddr[ETH_ALEN]) { NdpTable *ndp_table = &slirp->ndp_table; int i; DEBUG_CALL("ndp_table_add"); #if !defined(_WIN32) || (_WIN32_WINNT >= 0x0600) char addrstr[INET6_ADDRSTRLEN]; inet_ntop(AF_INET6, &(ip_addr), addrstr, INET6_ADDRSTRLEN); DEBUG_ARG("ip = %s", addrstr); #endif DEBUG_ARGS((dfd, " hw addr = %02x:%02x:%02x:%02x:%02x:%02x\n", ethaddr[0], ethaddr[1], ethaddr[2], ethaddr[3], ethaddr[4], ethaddr[5])); if (IN6_IS_ADDR_MULTICAST(&ip_addr) || IN6_IS_ADDR_UNSPECIFIED(&ip_addr)) { /* Do not register multicast or unspecified addresses */ DEBUG_CALL(" abort: do not register multicast or unspecified address"); return; } /* Search for an entry */ for (i = 0; i < NDP_TABLE_SIZE; i++) { if (in6_equal(&ndp_table->table[i].ip_addr, &ip_addr)) { DEBUG_CALL(" already in table: update the entry"); /* Update the entry */ memcpy(ndp_table->table[i].eth_addr, ethaddr, ETH_ALEN); return; } } /* No entry found, create a new one */ DEBUG_CALL(" create new entry"); ndp_table->table[ndp_table->next_victim].ip_addr = ip_addr; memcpy(ndp_table->table[ndp_table->next_victim].eth_addr, ethaddr, ETH_ALEN); ndp_table->next_victim = (ndp_table->next_victim + 1) % NDP_TABLE_SIZE; }
static int mount_local_flush(const char *path, struct fuse_file_info *fi) { DECL_G (); DEBUG_CALL ("%s", path); /* Just a stub. This method is called whenever FUSE wants to flush the * pending changes (f.ex. to attributes) to a file. Since we don't have * anything to do and don't want FUSE to think something went badly, * just return 0. */ return 0; }