++static int ipgre_header(struct sk_buff *skb, struct net_device *dev,
++ unsigned short type,
++ const void *daddr, const void *saddr, unsigned len)
++{
++ struct ip_tunnel *t = netdev_priv(dev);
++ struct iphdr *iph = (struct iphdr *)skb_push(skb, t->hlen);
++ __be16 *p = (__be16*)(iph+1);
++
++ memcpy(iph, &t->parms.iph, sizeof(struct iphdr));
++ p[0] = t->parms.o_flags;
++ p[1] = htons(type);
++
++ /*
++ * Set the source hardware address.
++ */
++
++ if (saddr)
++ memcpy(&iph->saddr, saddr, 4);
++
++ if (daddr) {
++ memcpy(&iph->daddr, daddr, 4);
++ return t->hlen;
++ }
++ if (iph->daddr && !ipv4_is_multicast(iph->daddr))
++ return t->hlen;
++
++ return -t->hlen;
++}
++
++static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr)
++{
++ struct iphdr *iph = (struct iphdr*) skb_mac_header(skb);
++ memcpy(haddr, &iph->saddr, 4);
++ return 4;
++}
++
++static const struct header_ops ipgre_header_ops = {
++ .create = ipgre_header,
++ .parse = ipgre_header_parse,
++};