ng_pppoe - RFC 2516 PPPoE protocol netgraph node type
The NGM_PPPOE_GET_STATUS control message can be used at any time to query the current status of the PPPoE module. The only statistics presently available are the total packet counts for input and output. This node does not yet support the NGM_TEXT_STATUS control message.
struct ngpppoestat {
u_int packets_in; /* packets in from Ethernet */
u_int packets_out; /* packets out towards Ethernet */
};
The three commands above use a common data structure:
struct ngpppoe_init_data {
char hook[NG_HOOKSIZ]; /* hook to monitor on */
u_int16_t data_len; /* service name length */
char data[0]; /* init data goes here */
};
The four commands above use a common data structure:
struct ngpppoe_sts {
char hook[NG_HOOKSIZ]; /* hook associated with event session */
};
ngctl msg fxp0:orphans pppoe_setmode '"3Com"'
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sysexits.h>
#include <errno.h>
#include <err.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <net/ethernet.h>
#include <netgraph.h>
#include <netgraph/ng_ether.h>
#include <netgraph/ng_pppoe.h>
#include <netgraph/ng_socket.h>
static int setup(char *ethername, char *service, char *sessname,
int *dfd, int *cfd);
int
main()
{
int fd1, fd2;
setup("xl0", NULL, "fred", &fd1, &fd2);
sleep (30);
}
static int
setup(char *ethername, char *service, char *sessname,
int *dfd, int *cfd)
{
struct ngm_connect ngc; /* connect */
struct ngm_mkpeer mkp; /* mkpeer */
/******** nodeinfo stuff **********/
u_char rbuf[2 * 1024];
struct ng_mesg *const resp = (struct ng_mesg *) rbuf;
struct hooklist *const hlist
= (struct hooklist *) resp->data;
struct nodeinfo *const ninfo = &hlist->nodeinfo;
int ch, no_hooks = 0;
struct linkinfo *link;
struct nodeinfo *peer;
/****message to connect PPPoE session*****/
struct {
struct ngpppoe_init_data idata;
char service[100];
} message;
/********tracking our little graph ********/
char path[100];
char source_ID[NG_NODESIZ];
char pppoe_node_name[100];
int k;
/*
* Create the data and control sockets
*/
if (NgMkSockNode(NULL, cfd, dfd) < 0) {
return (errno);
}
/*
* find the ether node of the name requested by asking it for
* it's inquiry information.
*/
if (strlen(ethername) > 16)
return (EINVAL);
sprintf(path, "%s:", ethername);
if (NgSendMsg(*cfd, path, NGM_GENERIC_COOKIE,
NGM_LISTHOOKS, NULL, 0) < 0) {
return (errno);
}
/*
* the command was accepted so it exists. Await the reply (It's
* almost certainly already waiting).
*/
if (NgRecvMsg(*cfd, resp, sizeof(rbuf), NULL) < 0) {
return (errno);
}
/**
* The following is available about the node:
* ninfo->name (string)
* ninfo->type (string)
* ninfo->id (u_int32_t)
* ninfo->hooks (u_int32_t) (count of hooks)
* check it is the correct type. and get it's ID for use
* with mkpeer later.
*/
if (strncmp(ninfo->type, NG_ETHER_NODE_TYPE,
strlen(NG_ETHER_NODE_TYPE)) != 0) {
return (EPROTOTYPE);
}
sprintf(source_ID, "[%08x]:", ninfo->id);
/*
* look for a hook already attached.
*/
for (k = 0; k < ninfo->hooks; k++) {
/**
* The following are available about each hook.
* link->ourhook (string)
* link->peerhook (string)
* peer->name (string)
* peer->type (string)
* peer->id (u_int32_t)
* peer->hooks (u_int32_t)
*/
link = &hlist->link[k];
peer = &hlist->link[k].nodeinfo;
/* Ignore debug hooks */
if (strcmp("debug", link->ourhook) == 0)
continue;
/* If the orphans hook is attached, use that */
if (strcmp(NG_ETHER_HOOK_ORPHAN,
link->ourhook) == 0) {
break;
}
/* the other option is the 'divert' hook */
if (strcmp("NG_ETHER_HOOK_DIVERT",
link->ourhook) == 0) {
break;
}
}
/*
* See if we found a hook there.
*/
if (k < ninfo->hooks) {
if (strcmp(peer->type, NG_PPPOE_NODE_TYPE) == 0) {
/*
* If it's a type PPPoE, we skip making one
* ourself, but we continue, using
* the existing one.
*/
sprintf(pppoe_node_name, "[%08x]:", peer->id);
} else {
/*
* There is already someone hogging the data,
* return an error. Some day we'll try
* daisy-chaining..
*/
return (EBUSY);
}
} else {
/*
* Try make a node of type PPPoE against node "ID"
* On hook NG_ETHER_HOOK_ORPHAN.
*/
snprintf(mkp.type, sizeof(mkp.type),
"%s", NG_PPPOE_NODE_TYPE);
snprintf(mkp.ourhook, sizeof(mkp.ourhook),
"%s", NG_ETHER_HOOK_ORPHAN);
snprintf(mkp.peerhook, sizeof(mkp.peerhook),
"%s", NG_PPPOE_HOOK_ETHERNET);
/* Send message */
if (NgSendMsg(*cfd, source_ID, NGM_GENERIC_COOKIE,
NGM_MKPEER, &mkp, sizeof(mkp)) < 0) {
return (errno);
}
/*
* Work out a name for the new node.
*/
sprintf(pppoe_node_name, "%s:%s",
source_ID, NG_ETHER_HOOK_ORPHAN);
}
/*
* We now have a PPPoE node attached to the Ethernet
* card. The Ethernet is addressed as ethername: The PPPoE
* node is addressed as pppoe_node_name: attach to it.
* Connect socket node to specified node Use the same hook
* name on both ends of the link.
*/
snprintf(ngc.path, sizeof(ngc.path), "%s", pppoe_node_name);
snprintf(ngc.ourhook, sizeof(ngc.ourhook), "%s", sessname);
snprintf(ngc.peerhook, sizeof(ngc.peerhook), "%s", sessname);
if (NgSendMsg(*cfd, ".:", NGM_GENERIC_COOKIE,
NGM_CONNECT, &ngc, sizeof(ngc)) < 0) {
return (errno);
}
#ifdef NONSTANDARD
/*
* In some cases we are speaking to 3Com hardware, so
* configure node to non-standard mode.
*/
if (NgSendMsg(*cfd, ngc.path, NGM_PPPOE_COOKIE,
NGM_PPPOE_SETMODE, NG_PPPOE_NONSTANDARD,
strlen(NG_PPPOE_NONSTANDARD) + 1) == -1) {
return (errno);
}
#endif
/*
* Send it a message telling it to start up.
*/
bzero(&message, sizeof(message));
snprintf(message.idata.hook, sizeof(message.idata.hook),
"%s", sessname);
if (service == NULL) {
message.idata.data_len = 0;
} else {
snprintf(message.idata.data,
sizeof(message.idata.data), "%s", service);
message.idata.data_len = strlen(service);
}
/* Tell session/hook to start up as a client */
if (NgSendMsg(*cfd, ngc.path,
NGM_PPPOE_COOKIE, NGM_PPPOE_CONNECT, &message.idata,
sizeof(message.idata) + message.idata.data_len) < 0) {
return (errno);
}
return (0);
}
|
Закладки на сайте Проследить за страницей |
Created 1996-2025 by Maxim Chirkov Добавить, Поддержать, Вебмастеру |