if (inet->inet_rcv_saddr && laddr &&
inet->inet_rcv_saddr != laddr) continue;
if (inet->inet_daddr && raddr && inet->inet_daddr != raddr) continue;
if (l2tp->conn_id != tunnel_id) continue;
goto found;
}
sk = NULL;
found: return sk;
}
/* When processing receive frames, there are two cases to * consider. Data frames consist of a non-zero session-id and an * optional cookie. Control frames consist of a regular L2TP header * preceded by 32-bits of zeros. * * L2TPv3 Session Header Over IP * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Session ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Cookie (optional, maximum 64 bits)... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * L2TPv3 Control Message Header Over IP * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | (32 bits of zeros) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |T|L|x|x|S|x|x|x|x|x|x|x| Ver | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Control Connection ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Ns | Nr | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * All control frames are passed to userspace.
*/ staticint l2tp_ip_recv(struct sk_buff *skb)
{ struct net *net = dev_net(skb->dev); struct l2tp_ip_net *pn; struct sock *sk;
u32 session_id;
u32 tunnel_id; unsignedchar *ptr, *optr; struct l2tp_session *session; struct l2tp_tunnel *tunnel = NULL; struct iphdr *iph;
pn = l2tp_ip_pernet(net);
if (!pskb_may_pull(skb, 4)) goto discard;
/* Point to L2TP header */
optr = skb->data;
ptr = skb->data;
session_id = ntohl(*((__be32 *)ptr));
ptr += 4;
/* RFC3931: L2TP/IP packets have the first 4 bytes containing * the session_id. If it is 0, the packet is a L2TP control * frame and the session_id value can be discarded.
*/ if (session_id == 0) {
__skb_pull(skb, 4); goto pass_up;
}
/* Ok, this is a data packet. Lookup the session. */
session = l2tp_v3_session_get(net, NULL, session_id); if (!session) goto discard;
tunnel = session->tunnel; if (!tunnel) goto discard_sess;
if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr)) goto discard_sess;
/* Copy user data into skb */
rc = memcpy_from_msg(skb_put(skb, len), msg, len); if (rc < 0) {
kfree_skb(skb); goto error;
}
if (connected)
rt = dst_rtable(__sk_dst_check(sk, 0));
rcu_read_lock(); if (!rt) { struct flowi4 *fl4 = &inet->cork.fl.u.ip4;
inet_sk_init_flowi4(inet, fl4);
/* Overwrite ->daddr if msg->msg_name was provided */ if (!connected)
fl4->daddr = daddr;
/* If this fails, retransmit mechanism of transport layer will * keep trying until route appears or the connection times * itself out.
*/
rt = ip_route_output_flow(sock_net(sk), fl4, sk); if (IS_ERR(rt)) goto no_route; if (connected) {
sk_setup_caps(sk, &rt->dst);
} else {
skb_dst_set(skb, &rt->dst); goto xmit;
}
}
/* We don't need to clone dst here, it is guaranteed to not disappear. * __dev_xmit_skb() might force a refcount if needed.
*/
skb_dst_set_noref(skb, &rt->dst);
xmit: /* Queue the packet to IP for output */
rc = ip_queue_xmit(sk, skb, &inet->cork.fl);
rcu_read_unlock();
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Chapman ");
MODULE_DESCRIPTION("L2TP over IP");
MODULE_VERSION("1.0");
/* Use the values of SOCK_DGRAM (2) as type and IPPROTO_L2TP (115) as protocol, * because __stringify doesn't like enums
*/
MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_INET, 115, 2);
MODULE_ALIAS_NET_PF_PROTO(PF_INET, 115);
Messung V0.5
¤ Dauer der Verarbeitung: 0.15 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.