int __cdecl WRAPPER(FUNCTION)( ARGDECL(FUNCTION) ) { /* invoke the wrapped MSVC 'exec' or 'spawn' system service * enclosing the passed arguments in double quotes, as required, * so that the (broken) default parsing in the MSVC runtime doesn't * split them at whitespace */ return( WRAPPED(FUNCTION)( USEARGS(FUNCTION) )); }
static int pptp_xmit(struct ppp_channel *chan, struct sk_buff *skb) { struct sock *sk = (struct sock *) chan->private; struct pppox_sock *po = pppox_sk(sk); struct pptp_opt *opt=&po->proto.pptp; struct pptp_gre_header *hdr; unsigned int header_len=sizeof(*hdr); int len=skb?skb->len:0; int err=0; int window; struct rtable *rt; /* Route to the other host */ struct net_device *tdev; /* Device to other host */ struct iphdr *iph; /* Our new IP header */ int max_headroom; /* The extra header space needed */ INC_TX_PACKETS; spin_lock_bh(&opt->xmit_lock); window=WRAPPED(opt->ack_recv,opt->seq_sent)?(__u32)0xffffffff-opt->seq_sent+opt->ack_recv:opt->seq_sent-opt->ack_recv; if (!skb){ if (opt->ack_sent == opt->seq_recv) goto exit; }else if (window>opt->window){ __set_bit(PPTP_FLAG_PAUSE,(unsigned long*)&opt->flags); #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) mod_timer(&opt->ack_timeout_timer,opt->stat->rtt/100*HZ/10000); #else schedule_delayed_work(&opt->ack_timeout_work,opt->stat->rtt/100*HZ/10000); #endif goto exit; } #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) { struct rt_key key = { .dst=opt->dst_addr.sin_addr.s_addr, .src=opt->src_addr.sin_addr.s_addr, .tos=RT_TOS(0), }; if ((err=ip_route_output_key(&rt, &key))) { goto tx_error; } } #else { struct flowi fl = { .oif = 0, .nl_u = { .ip4_u = { .daddr = opt->dst_addr.sin_addr.s_addr, .saddr = opt->src_addr.sin_addr.s_addr, .tos = RT_TOS(0) } }, .proto = IPPROTO_GRE }; if ((err=ip_route_output_key(&rt, &fl))) { goto tx_error; } } #endif tdev = rt->u.dst.dev; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) max_headroom = ((tdev->hard_header_len+15)&~15) + sizeof(*iph)+sizeof(*hdr)+2; #else max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph)+sizeof(*hdr)+2; #endif if (!skb){ skb=dev_alloc_skb(max_headroom); if (!skb) { ip_rt_put(rt); goto tx_error; } skb_reserve(skb,max_headroom-skb_headroom(skb)); }else if (skb_headroom(skb) < max_headroom || skb_cloned(skb) || skb_shared(skb)) { struct sk_buff *new_skb = skb_realloc_headroom(skb, max_headroom); if (!new_skb) { ip_rt_put(rt); goto tx_error; } if (skb->sk) skb_set_owner_w(new_skb, skb->sk); kfree_skb(skb); skb = new_skb; } if (skb->len){ int islcp; unsigned char *data=skb->data; islcp=((data[0] << 8) + data[1])== PPP_LCP && 1 <= data[2] && data[2] <= 7; /* compress protocol field */ if ((opt->ppp_flags & SC_COMP_PROT) && data[0]==0 && !islcp) skb_pull(skb,1); /* * Put in the address/control bytes if necessary */ if ((opt->ppp_flags & SC_COMP_AC) == 0 || islcp) { data=skb_push(skb,2); data[0]=0xff; data[1]=0x03; } } len=skb->len; if (len==0) header_len-=sizeof(hdr->seq); if (opt->ack_sent == opt->seq_recv) header_len-=sizeof(hdr->ack); // Push down and install GRE header skb_push(skb,header_len); hdr=(struct pptp_gre_header *)(skb->data); hdr->flags = PPTP_GRE_FLAG_K; hdr->ver = PPTP_GRE_VER; hdr->protocol = htons(PPTP_GRE_PROTO); hdr->call_id = htons(opt->dst_addr.call_id); if (!len){ hdr->payload_len = 0; hdr->ver |= PPTP_GRE_FLAG_A; /* ack is in odd place because S == 0 */ hdr->seq = htonl(opt->seq_recv); opt->ack_sent = opt->seq_recv; opt->stat->tx_acks++; }else { hdr->flags |= PPTP_GRE_FLAG_S; hdr->seq = htonl(opt->seq_sent++); if (log_level>=3 && opt->seq_sent<=log_packets) printk(KERN_INFO"PPTP[%i]: send packet: seq=%i",opt->src_addr.call_id,opt->seq_sent); if (opt->ack_sent != opt->seq_recv) { /* send ack with this message */ hdr->ver |= PPTP_GRE_FLAG_A; hdr->ack = htonl(opt->seq_recv); opt->ack_sent = opt->seq_recv; if (log_level>=3 && opt->seq_sent<=log_packets) printk(" ack=%i",opt->seq_recv); } hdr->payload_len = htons(len); if (log_level>=3 && opt->seq_sent<=log_packets) printk("\n"); } /* * Push down and install the IP header. */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) skb->transport_header = skb->network_header; skb_push(skb, sizeof(*iph)); skb_reset_network_header(skb); #else skb->h.raw = skb->nh.raw; skb->nh.raw = skb_push(skb, sizeof(*iph)); #endif memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) iph = ip_hdr(skb); #else iph = skb->nh.iph; #endif iph->version = 4; iph->ihl = sizeof(struct iphdr) >> 2; iph->frag_off = 0;//df; iph->protocol = IPPROTO_GRE; iph->tos = 0; iph->daddr = rt->rt_dst; iph->saddr = rt->rt_src; #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) iph->ttl = sysctl_ip_default_ttl; #else iph->ttl = dst_metric(&rt->u.dst, RTAX_HOPLIMIT); #endif iph->tot_len = htons(skb->len); dst_release(skb->dst); skb->dst = &rt->u.dst; nf_reset(skb); skb->ip_summed = CHECKSUM_NONE; ip_select_ident(iph, &rt->u.dst, NULL); ip_send_check(iph); err = NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, dst_output); wake_up(&opt->wait); if (err == NET_XMIT_SUCCESS || err == NET_XMIT_CN) { opt->stat->tx_sent++; if (!opt->stat->pt_seq){ opt->stat->pt_seq = opt->seq_sent; do_gettimeofday(&opt->stat->pt_time); } }else{ INC_TX_ERRORS; opt->stat->tx_failed++; } spin_unlock_bh(&opt->xmit_lock); return 1; tx_error: INC_TX_ERRORS; opt->stat->tx_failed++; if (!len) kfree_skb(skb); spin_unlock_bh(&opt->xmit_lock); return 1; exit: spin_unlock_bh(&opt->xmit_lock); return 0; }
/*** decaps_gre ***************************************************************/ int decaps_gre (int fd, callback_t callback, int cl) { unsigned char buffer[PACKET_MAX + 64 /*ip header*/]; struct pptp_gre_header *header; int status, ip_len = 0; static int first = 1; unsigned int headersize; unsigned int payload_len; u_int32_t seq; if ((status = read (fd, buffer, sizeof(buffer))) <= 0) { warn("short read (%d): %s", status, strerror(errno)); stats.rx_errors++; return -1; } /* strip off IP header, if present */ if ((buffer[0] & 0xF0) == 0x40) ip_len = (buffer[0] & 0xF) * 4; header = (struct pptp_gre_header *)(buffer + ip_len); /* verify packet (else discard) */ if ( /* version should be 1 */ ((ntoh8(header->ver) & 0x7F) != PPTP_GRE_VER) || /* PPTP-GRE protocol for PPTP */ (ntoh16(header->protocol) != PPTP_GRE_PROTO)|| /* flag C should be clear */ PPTP_GRE_IS_C(ntoh8(header->flags)) || /* flag R should be clear */ PPTP_GRE_IS_R(ntoh8(header->flags)) || /* flag K should be set */ (!PPTP_GRE_IS_K(ntoh8(header->flags))) || /* routing and recursion ctrl = 0 */ ((ntoh8(header->flags)&0xF) != 0)) { /* if invalid, discard this packet */ warn("Discarding GRE: %X %X %X %X %X %X", ntoh8(header->ver)&0x7F, ntoh16(header->protocol), PPTP_GRE_IS_C(ntoh8(header->flags)), PPTP_GRE_IS_R(ntoh8(header->flags)), PPTP_GRE_IS_K(ntoh8(header->flags)), ntoh8(header->flags) & 0xF); stats.rx_invalid++; return 0; } /* silently discard packets not for this call */ if (ntoh16(header->call_id) != pptp_gre_call_id) return 0; /* test if acknowledgement present */ if (PPTP_GRE_IS_A(ntoh8(header->ver))) { u_int32_t ack = (PPTP_GRE_IS_S(ntoh8(header->flags)))? header->ack:header->seq; /* ack in different place if S = 0 */ ack = ntoh32( ack); if (ack > ack_recv) ack_recv = ack; /* also handle sequence number wrap-around */ if (WRAPPED(ack,ack_recv)) ack_recv = ack; if (ack_recv == stats.pt.seq) { int rtt = time_now_usecs() - stats.pt.time; stats.rtt = (stats.rtt + rtt) / 2; } } /* test if payload present */ if (!PPTP_GRE_IS_S(ntoh8(header->flags))) return 0; /* ack, but no payload */ headersize = sizeof(*header); payload_len = ntoh16(header->payload_len); seq = ntoh32(header->seq); /* no ack present? */ if (!PPTP_GRE_IS_A(ntoh8(header->ver))) headersize -= sizeof(header->ack); /* check for incomplete packet (length smaller than expected) */ if (status - headersize < payload_len) { warn("discarding truncated packet (expected %d, got %d bytes)", payload_len, status - headersize); stats.rx_truncated++; return 0; } /* check for expected sequence number */ if ( first || (seq == seq_recv + 1)) { /* wrap-around safe */ if ( log_level >= 2 ) log("accepting packet %d", seq); stats.rx_accepted++; first = 0; seq_recv = seq; return callback(cl, buffer + ip_len + headersize, payload_len); /* out of order, check if the number is too low and discard the packet. * (handle sequence number wrap-around, and try to do it right) */ } else if ( seq < seq_recv + 1 || WRAPPED(seq_recv, seq) ) { if ( log_level >= 1 ) log("discarding duplicate or old packet %d (expecting %d)", seq, seq_recv + 1); stats.rx_underwin++; /* sequence number too high, is it reasonably close? */ } else if ( seq < seq_recv + MISSING_WINDOW || WRAPPED(seq, seq_recv + MISSING_WINDOW) ) { stats.rx_buffered++; if ( log_level >= 1 ) log("%s packet %d (expecting %d, lost or reordered)", disable_buffer ? "accepting" : "buffering", seq, seq_recv+1); if ( disable_buffer ) { seq_recv = seq; stats.rx_lost += seq - seq_recv - 1; return callback(cl, buffer + ip_len + headersize, payload_len); } else { pqueue_add(seq, buffer + ip_len + headersize, payload_len); } /* no, packet must be discarded */ } else { if ( log_level >= 1 ) warn("discarding bogus packet %d (expecting %d)", seq, seq_recv + 1); stats.rx_overwin++; } return 0; }
/* ** Clear the line to the new width (just reset the line width). */ Boolean _DtTermPrimBufferClearLineWc ( const TermBuffer tb, const short row, short newWidth ) { TermLine line; TermCharInfoRec charInfo; short newLength; /* ** Some simple bounds checking. */ if (!VALID_ROW(tb, row)) { return(False); } /* ** force the width to the desired value ** ** (We take the direct approach because _DtTermPrimBufferSetLineWidth ** doesn't allow the line width to decrease.) */ line = LINE_OF_TBUF(tb, row); /* ** if this line is part of the selection, disown the selection... */ if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)), MAX(newWidth, WIDTH(line)))) { (void) _DtTermPrimSelectDisown(WIDGET(tb)); } /* ** Clip the new width to the buffer width. */ newWidth = MIN(newWidth, COLS(tb)); if (newWidth < WIDTH(line)) { if (newWidth == 0) { newLength = 0; } else { /* ** handle the case of clearing the second column of a two column ** character... */ _DtTermPrimGetCharacterInfo(tb, row, MAX(0, newWidth - 1), &charInfo); if ((charInfo.width == 2 ) && (charInfo.startCol == MAX(0, newWidth - 1))) { /* ** we are clearing column 2 of 2, replace column 1 of 1 with ** a space... */ *charInfo.u.pwc = L' '; } newLength = charInfo.idx + 1; } /* ** Call the helper function if it exists */ if (CLEAR_LINE(tb)) { (*CLEAR_LINE(tb))(tb, row, newWidth); } WRAPPED(line) = False; WIDTH(line) = newWidth; LENGTH(line) = newLength; } return(True); }