Fix ng_pppoe(4) after turning off "autosrc feature" on ng_ether(4).

- Store the Ethernet header in node softc.
- Initialize header with dst addr and ethertype in node
  constructor method.
- In node connect method send NGM_ETHER_GET_ENADDR message
  downwards.
- If received reply from ng_ether(4) store the src addr
  in softc.
- Add NGM_PPPOE_SETENDADDR message that allows user to
  override the address with whatever he/she wants.
This commit is contained in:
Gleb Smirnoff 2006-08-09 09:56:58 +00:00
parent de6f1c7c6c
commit b1ba28df1d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=161117
3 changed files with 93 additions and 23 deletions

View File

@ -35,7 +35,7 @@
.\" $FreeBSD$
.\" $Whistle: ng_pppoe.8,v 1.1 1999/01/25 23:46:27 archie Exp $
.\"
.Dd January 27, 2006
.Dd August 9, 2006
.Dt NG_PPPOE 4
.Os
.Sh NAME
@ -70,7 +70,14 @@ This node type supports the following hooks:
.Pp
.Bl -tag -width [unspecified]
.It Dv ethernet
The hook that should normally be connected to an Ethernet node.
The hook that should normally be connected to an
.Xr ng_ether 4
node.
Once connected,
.Nm
will send a message down this hook to determine Ethernet address of
the underlying node.
Obtained address will be stored and then used for outgoing datagrams.
.It Dv debug
Presently no use.
.It Dv [unspecified]
@ -227,6 +234,15 @@ the next session in the proprietary 3Com mode:
.Bd -literal -offset indent
ngctl msg fxp0:orphans pppoe_setmode '"3Com"'
.Ed
.It Dv NGM_PPPOE_SETENADDR
Set the node Ethernet address for outgoing datagrams.
This message is important when node failed to obtain Ethernet address
from peer on
.Dv ethernet
hook, or when user wants to override this address with another one.
.Tn ASCII
form of this message is
.Qq Li setenaddr .
.El
.Sh SHUTDOWN
This node shuts down upon receipt of a
@ -466,6 +482,7 @@ setup(char *ethername, char *service, char *sessname,
.Sh SEE ALSO
.Xr netgraph 3 ,
.Xr netgraph 4 ,
.Xr ng_ether 4 ,
.Xr ng_ppp 4 ,
.Xr ng_socket 4 ,
.Xr ngctl 8 ,

View File

@ -55,6 +55,7 @@
#include <netgraph/netgraph.h>
#include <netgraph/ng_parse.h>
#include <netgraph/ng_pppoe.h>
#include <netgraph/ng_ether.h>
#ifdef NG_SEPARATE_MALLOC
MALLOC_DEFINE(M_NETGRAPH_PPPOE, "netgraph_pppoe", "netgraph pppoe node");
@ -74,6 +75,7 @@ static ng_constructor_t ng_pppoe_constructor;
static ng_rcvmsg_t ng_pppoe_rcvmsg;
static ng_shutdown_t ng_pppoe_shutdown;
static ng_newhook_t ng_pppoe_newhook;
static ng_connect_t ng_pppoe_connect;
static ng_rcvdata_t ng_pppoe_rcvdata;
static ng_disconnect_t ng_pppoe_disconnect;
@ -158,6 +160,13 @@ static const struct ng_cmdlist ng_pppoe_cmds[] = {
NULL,
&ng_parse_string_type
},
{
NGM_PPPOE_COOKIE,
NGM_PPPOE_SETENADDR,
"setenaddr",
&ng_parse_enaddr_type,
NULL
},
{ 0 }
};
@ -169,6 +178,7 @@ static struct ng_type typestruct = {
.rcvmsg = ng_pppoe_rcvmsg,
.shutdown = ng_pppoe_shutdown,
.newhook = ng_pppoe_newhook,
.connect = ng_pppoe_connect,
.rcvdata = ng_pppoe_rcvdata,
.disconnect = ng_pppoe_disconnect,
.cmdlist = ng_pppoe_cmds,
@ -229,16 +239,6 @@ typedef struct sess_con *sessp;
#define NG_PPPOE_SESSION_NODE(sp) NG_HOOK_NODE(sp->hook)
static const struct ether_header eh_standard =
{{0xff,0xff,0xff,0xff,0xff,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00},
ETHERTYPE_PPPOE_DISC};
static const struct ether_header eh_3Com =
{{0xff,0xff,0xff,0xff,0xff,0xff},
{0x00,0x00,0x00,0x00,0x00,0x00},
ETHERTYPE_PPPOE_3COM_DISC};
/*
* Information we store for each node
*/
@ -251,7 +251,7 @@ struct PPPoE {
uint32_t flags;
#define COMPAT_3COM 0x00000001
#define COMPAT_DLINK 0x00000002
const struct ether_header *eh; /* standard PPPoE or 3Com? */
struct ether_header eh;
};
typedef struct PPPoE *priv_p;
@ -635,7 +635,8 @@ ng_pppoe_constructor(node_p node)
privp->node = node;
/* Initialize to standard mode. */
privp->eh = &eh_standard;
memset(&privp->eh.ether_dhost, 0xff, ETHER_ADDR_LEN);
privp->eh.ether_type = ETHERTYPE_PPPOE_DISC;
CTR3(KTR_NET, "%20s: created node [%x] (%p)",
__func__, node->nd_ID, node);
@ -683,6 +684,38 @@ ng_pppoe_newhook(node_p node, hook_p hook, const char *name)
return(0);
}
/*
* Hook has been added successfully. Request the MAC address of
* the underlying Ethernet node.
*/
static int
ng_pppoe_connect(hook_p hook)
{
const priv_p privp = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
struct ng_mesg *msg;
int error = 0;
if (hook != privp->ethernet_hook)
return (0);
/*
* If this is Ethernet hook, then request MAC address
* from our downstream.
*/
NG_MKMESSAGE(msg, NGM_ETHER_COOKIE, NGM_ETHER_GET_ENADDR, 0, M_NOWAIT);
if (msg == NULL)
return (ENOBUFS);
/*
* Our hook and peer hook have HK_INVALID flag set,
* so we can't use NG_SEND_MSG_HOOK() macro here.
*/
NG_SEND_MSG_ID(error, privp->node, msg,
NG_NODE_ID(NG_PEER_NODE(privp->ethernet_hook)),
NG_NODE_ID(privp->node));
return (error);
}
/*
* Get a netgraph control message.
* Check it is one we understand. If needed, send a response.
@ -797,8 +830,7 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
neg->m->m_len = sizeof(struct pppoe_full_hdr);
neg->pkt = mtod(neg->m, union packet*);
memcpy((void *)&neg->pkt->pkt_header.eh,
(const void *)privp->eh,
sizeof(struct ether_header));
&privp->eh, sizeof(struct ether_header));
neg->pkt->pkt_header.ph.ver = 0x1;
neg->pkt->pkt_header.ph.type = 0x1;
neg->pkt->pkt_header.ph.sid = 0x0000;
@ -917,13 +949,14 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
if (len == strlen(NG_PPPOE_STANDARD) &&
(strncmp(NG_PPPOE_STANDARD, s, len) == 0)) {
privp->flags = 0;
privp->eh = &eh_standard;
privp->eh.ether_type = ETHERTYPE_PPPOE_DISC;
break;
}
if (len == strlen(NG_PPPOE_3COM) &&
(strncmp(NG_PPPOE_3COM, s, len) == 0)) {
privp->flags |= COMPAT_3COM;
privp->eh = &eh_3Com;
privp->eh.ether_type =
ETHERTYPE_PPPOE_3COM_DISC;
break;
}
if (len == strlen(NG_PPPOE_DLINK) &&
@ -969,10 +1002,30 @@ ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook)
}
break;
}
case NGM_PPPOE_SETENADDR:
if (msg->header.arglen != ETHER_ADDR_LEN)
LEAVE(EINVAL);
bcopy(msg->data, &privp->eh.ether_shost,
ETHER_ADDR_LEN);
break;
default:
LEAVE(EINVAL);
}
break;
case NGM_ETHER_COOKIE:
if (!(msg->header.flags & NGF_RESP))
LEAVE(EINVAL);
switch (msg->header.cmd) {
case NGM_ETHER_GET_ENADDR:
if (msg->header.arglen != ETHER_ADDR_LEN)
LEAVE(EINVAL);
bcopy(msg->data, &privp->eh.ether_shost,
ETHER_ADDR_LEN);
break;
default:
error = EINVAL;
}
break;
default:
LEAVE(EINVAL);
}
@ -1006,11 +1059,10 @@ pppoe_start(sessp sp)
sp->state = PPPOE_SINIT;
/*
* Reset the packet header to broadcast. Since we are
* in a client
* mode use configured ethertype.
* in a client mode use configured ethertype.
*/
memcpy((void *)&sp->neg->pkt->pkt_header.eh,
(const void *)privp->eh, sizeof(struct ether_header));
memcpy((void *)&sp->neg->pkt->pkt_header.eh, &privp->eh,
sizeof(struct ether_header));
sp->neg->pkt->pkt_header.ph.code = PADI_CODE;
uniqtag.hdr.tag_type = PTT_HOST_UNIQ;
uniqtag.hdr.tag_len = htons((u_int16_t)sizeof(uniqtag.data));

View File

@ -85,8 +85,9 @@ enum cmd {
NGM_PPPOE_ACNAME = 9, /* AC_NAME for informational purposes */
NGM_PPPOE_GET_STATUS = 10, /* data in/out */
NGM_PPPOE_SESSIONID = 11, /* Session_ID for informational purposes */
NGM_PPPOE_SETMODE = 12, /* set to standard or 3Com mode */
NGM_PPPOE_SETMODE = 12, /* set to standard or compat modes */
NGM_PPPOE_GETMODE = 13, /* see current mode */
NGM_PPPOE_SETENADDR = 14, /* set Ethernet address */
};
/***********************