xref: /openbsd/usr.sbin/npppd/npppd/npppd_ctl.c (revision e83549be)
1*e83549beSgoda /*	$OpenBSD: npppd_ctl.c,v 1.16 2017/08/11 16:25:59 goda Exp $ */
2e109dc18Syasuoka 
30fbf3537Syasuoka /*-
40fbf3537Syasuoka  * Copyright (c) 2009 Internet Initiative Japan Inc.
50fbf3537Syasuoka  * All rights reserved.
60fbf3537Syasuoka  *
70fbf3537Syasuoka  * Redistribution and use in source and binary forms, with or without
80fbf3537Syasuoka  * modification, are permitted provided that the following conditions
90fbf3537Syasuoka  * are met:
100fbf3537Syasuoka  * 1. Redistributions of source code must retain the above copyright
110fbf3537Syasuoka  *    notice, this list of conditions and the following disclaimer.
120fbf3537Syasuoka  * 2. Redistributions in binary form must reproduce the above copyright
130fbf3537Syasuoka  *    notice, this list of conditions and the following disclaimer in the
140fbf3537Syasuoka  *    documentation and/or other materials provided with the distribution.
150fbf3537Syasuoka  *
160fbf3537Syasuoka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
170fbf3537Syasuoka  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
180fbf3537Syasuoka  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
190fbf3537Syasuoka  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
200fbf3537Syasuoka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
210fbf3537Syasuoka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
220fbf3537Syasuoka  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
230fbf3537Syasuoka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
240fbf3537Syasuoka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
250fbf3537Syasuoka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
260fbf3537Syasuoka  * SUCH DAMAGE.
270fbf3537Syasuoka  */
280fbf3537Syasuoka #include <sys/socket.h>
2934682664Syasuoka #include <sys/ioctl.h>
3034682664Syasuoka #include <net/if.h>
310fbf3537Syasuoka #include <netinet/in.h>
3234682664Syasuoka #include <net/pipex.h>
330fbf3537Syasuoka 
340fbf3537Syasuoka #include <errno.h>
350fbf3537Syasuoka #include <event.h>
360fbf3537Syasuoka #include <stddef.h>
370fbf3537Syasuoka #include <stdio.h>
380fbf3537Syasuoka #include <stdlib.h>
390fbf3537Syasuoka #include <string.h>
400fbf3537Syasuoka 
410fbf3537Syasuoka #include "radish.h"
4234682664Syasuoka #include "npppd_local.h"
4334682664Syasuoka #include "npppd.h"
4434682664Syasuoka #include "log.h"
450fbf3537Syasuoka 
4634682664Syasuoka struct stopped_ppp {
4734682664Syasuoka 	struct npppd_who          ppp_who;
4834682664Syasuoka 	TAILQ_ENTRY(stopped_ppp)  entry;
4934682664Syasuoka };
500fbf3537Syasuoka 
5134682664Syasuoka struct npppd_ctl {
5234682664Syasuoka 	u_int                     *started_ppp;
5334682664Syasuoka 	int                        started_ppp_pos;
5434682664Syasuoka 	int                        started_ppp_siz;
5534682664Syasuoka 	TAILQ_HEAD(, stopped_ppp)  stopped_ppps;
5634682664Syasuoka 	npppd                     *npppd;
5734682664Syasuoka 	bool                       is_monitoring;
5834682664Syasuoka 	bool                       responding;
5934682664Syasuoka };
6034682664Syasuoka 
6134682664Syasuoka static int npppd_ctl_who_walk_rd(struct radish *, void *);
6234682664Syasuoka static int npppd_ctl_who0 (struct npppd_ctl *, bool);
6334682664Syasuoka static void npppd_who_init (struct npppd_who *, npppd_ppp *);
640fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
6534682664Syasuoka static int npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp);
660fbf3537Syasuoka #endif
670fbf3537Syasuoka 
6834682664Syasuoka struct npppd_ctl *
npppd_ctl_create(npppd * _this)6934682664Syasuoka npppd_ctl_create(npppd *_this)
700fbf3537Syasuoka {
7134682664Syasuoka 	struct npppd_ctl *ctl;
7234682664Syasuoka 
731f03f1b3Syasuoka 	if ((ctl = calloc(1, sizeof(struct npppd_ctl))) == NULL)
7434682664Syasuoka 		return (NULL);
7534682664Syasuoka 	ctl->npppd = _this;
7634682664Syasuoka 	TAILQ_INIT(&ctl->stopped_ppps);
7734682664Syasuoka 
7834682664Syasuoka 	return (ctl);
790fbf3537Syasuoka }
800fbf3537Syasuoka 
8134682664Syasuoka void
npppd_ctl_destroy(struct npppd_ctl * _this)8234682664Syasuoka npppd_ctl_destroy(struct npppd_ctl *_this)
8334682664Syasuoka {
8434682664Syasuoka 	if (_this != NULL) {
8534682664Syasuoka 		free(_this->started_ppp);
8634682664Syasuoka 		free(_this);
8734682664Syasuoka 	}
8834682664Syasuoka }
8934682664Syasuoka 
900fbf3537Syasuoka int
npppd_ctl_who(struct npppd_ctl * _this)9134682664Syasuoka npppd_ctl_who(struct npppd_ctl *_this)
920fbf3537Syasuoka {
9334682664Syasuoka 	return (npppd_ctl_who0(_this, false));
940fbf3537Syasuoka }
950fbf3537Syasuoka 
9634682664Syasuoka int
npppd_ctl_monitor(struct npppd_ctl * _this)9734682664Syasuoka npppd_ctl_monitor(struct npppd_ctl *_this)
9834682664Syasuoka {
9934682664Syasuoka 	_this->is_monitoring = true;
10034682664Syasuoka 	return (0);
10134682664Syasuoka }
10234682664Syasuoka 
10334682664Syasuoka int
npppd_ctl_who_and_monitor(struct npppd_ctl * _this)10434682664Syasuoka npppd_ctl_who_and_monitor(struct npppd_ctl *_this)
10534682664Syasuoka {
10634682664Syasuoka 	return (npppd_ctl_who0(_this, true));
10734682664Syasuoka }
10834682664Syasuoka 
10934682664Syasuoka static int
npppd_ctl_who0(struct npppd_ctl * _this,bool is_monitoring)11034682664Syasuoka npppd_ctl_who0(struct npppd_ctl *_this, bool is_monitoring)
11134682664Syasuoka {
11234682664Syasuoka 	_this->is_monitoring = is_monitoring;
11334682664Syasuoka 	_this->responding = true;
11434682664Syasuoka 	if (rd_walktree(_this->npppd->rd, npppd_ctl_who_walk_rd, _this) != 0)
11534682664Syasuoka 		return (-1);
11634682664Syasuoka 	return (0);
11734682664Syasuoka }
11834682664Syasuoka 
11934682664Syasuoka int
npppd_ctl_add_started_ppp_id(struct npppd_ctl * _this,u_int ppp_id)12034682664Syasuoka npppd_ctl_add_started_ppp_id(struct npppd_ctl *_this, u_int ppp_id)
12134682664Syasuoka {
12234682664Syasuoka 	int    started_ppp_siz;
12334682664Syasuoka 	u_int *started_ppp;
12434682664Syasuoka 
12534682664Syasuoka 	if (!_this->is_monitoring && !_this->responding)
12634682664Syasuoka 		return (-1);
12734682664Syasuoka 	if (_this->started_ppp_pos + 1 >= _this->started_ppp_siz) {
12834682664Syasuoka 		started_ppp_siz = _this->started_ppp_siz + 128;
12915c8733cSderaadt 		started_ppp = reallocarray(_this->started_ppp,
13015c8733cSderaadt 		    started_ppp_siz, sizeof(u_int));
13134682664Syasuoka 		if (started_ppp == NULL)
13234682664Syasuoka 			return (-1);
13334682664Syasuoka 		_this->started_ppp = started_ppp;
13434682664Syasuoka 		_this->started_ppp_siz = started_ppp_siz;
1350fbf3537Syasuoka 	}
13634682664Syasuoka 	_this->started_ppp[_this->started_ppp_pos++] = ppp_id;
1370fbf3537Syasuoka 
13834682664Syasuoka 	/* reset the event */
13934682664Syasuoka 
14034682664Syasuoka 	return (0);
1410fbf3537Syasuoka }
1420fbf3537Syasuoka 
14334682664Syasuoka int
npppd_ctl_add_stopped_ppp(struct npppd_ctl * _this,npppd_ppp * ppp)14434682664Syasuoka npppd_ctl_add_stopped_ppp(struct npppd_ctl *_this, npppd_ppp *ppp)
1450fbf3537Syasuoka {
14634682664Syasuoka 	struct stopped_ppp *stopped;
14734682664Syasuoka 
14834682664Syasuoka 	if (!_this->is_monitoring)
14934682664Syasuoka 		return (-1);
15034682664Syasuoka 	if ((stopped = malloc(sizeof(struct stopped_ppp))) == NULL) {
15134682664Syasuoka 		log_warn("malloc() failed in %s()", __func__);
15234682664Syasuoka 		return (-1);
1530fbf3537Syasuoka 	}
15434682664Syasuoka 	npppd_who_init(&stopped->ppp_who, ppp);
15534682664Syasuoka 	TAILQ_INSERT_TAIL(&_this->stopped_ppps, stopped, entry);
15634682664Syasuoka 
15734682664Syasuoka 	return (0);
1580fbf3537Syasuoka }
1590fbf3537Syasuoka 
16034682664Syasuoka static int
npppd_ctl_who_walk_rd(struct radish * rd,void * ctx)16134682664Syasuoka npppd_ctl_who_walk_rd(struct radish *rd, void *ctx)
1620fbf3537Syasuoka {
16334682664Syasuoka 	struct npppd_ctl *_this = ctx;
16434682664Syasuoka 	struct sockaddr_npppd *snp;
1650fbf3537Syasuoka 	npppd_ppp             *ppp;
1660fbf3537Syasuoka 
16734682664Syasuoka 	snp = rd->rd_rtent;
16834682664Syasuoka 	if (snp->snp_type == SNP_PPP) {
16934682664Syasuoka 		ppp = snp->snp_data_ptr;
17034682664Syasuoka 		if (npppd_ctl_add_started_ppp_id(_this, ppp->id) != 0)
17134682664Syasuoka 			return (-1);
1720fbf3537Syasuoka 	}
1730fbf3537Syasuoka 
17434682664Syasuoka 	return (0);
1750fbf3537Syasuoka }
1760fbf3537Syasuoka 
17734682664Syasuoka int
npppd_ctl_disconnect(struct npppd_ctl * _this,u_int * ppp_id,int count)17834682664Syasuoka npppd_ctl_disconnect(struct npppd_ctl *_this, u_int *ppp_id, int count)
179363e4d4bSyasuoka {
180363e4d4bSyasuoka 	int        i, n;
181363e4d4bSyasuoka 	npppd_ppp *ppp;
182363e4d4bSyasuoka 
18334682664Syasuoka 	for (n = 0, i = 0; i < count; i++) {
18434682664Syasuoka 		if ((ppp = npppd_get_ppp_by_id(_this->npppd, ppp_id[i]))
18534682664Syasuoka 		    != NULL) {
186363e4d4bSyasuoka 			ppp_stop(ppp, NULL);
18734682664Syasuoka 			n++;
188363e4d4bSyasuoka 		}
189363e4d4bSyasuoka 	}
1907a7bab9dSyasuoka 
19134682664Syasuoka 	return (n);
19234682664Syasuoka }
19334682664Syasuoka 
19434682664Syasuoka int
npppd_ctl_imsg_compose(struct npppd_ctl * _this,struct imsgbuf * ibuf)19534682664Syasuoka npppd_ctl_imsg_compose(struct npppd_ctl *_this, struct imsgbuf *ibuf)
19634682664Syasuoka {
19734682664Syasuoka 	int                    i, cnt;
19834682664Syasuoka 	u_char                 pktbuf[MAX_IMSGSIZE - IMSG_HEADER_SIZE];
19934682664Syasuoka 	struct npppd_who_list *who_list;
20034682664Syasuoka 	npppd_ppp             *ppp;
20134682664Syasuoka 	struct stopped_ppp    *e, *t;
20234682664Syasuoka 
20334682664Syasuoka 	if (ibuf->w.queued)
20434682664Syasuoka 		return (0);
20534682664Syasuoka 
20634682664Syasuoka 	cnt = 0;
20734682664Syasuoka 	if (!TAILQ_EMPTY(&_this->stopped_ppps)) {
20834682664Syasuoka 		who_list = (struct npppd_who_list *)pktbuf;
20934682664Syasuoka 		who_list->more_data = 0;
21034682664Syasuoka 		TAILQ_FOREACH_SAFE(e, &_this->stopped_ppps, entry, t) {
21134682664Syasuoka 			if (offsetof(struct npppd_who_list, entry[cnt + 1])
21234682664Syasuoka 			    > sizeof(pktbuf)) {
21334682664Syasuoka 				who_list->more_data = 1;
21434682664Syasuoka 				break;
21534682664Syasuoka 			}
21634682664Syasuoka 			TAILQ_REMOVE(&_this->stopped_ppps, e, entry);
21734682664Syasuoka 			memcpy(&who_list->entry[cnt], &e->ppp_who,
21834682664Syasuoka 			    sizeof(who_list->entry[0]));
21934682664Syasuoka 			cnt++;
22034682664Syasuoka 			free(e);
22134682664Syasuoka 		}
22234682664Syasuoka 		who_list->entry_count = cnt;
22334682664Syasuoka 		if (imsg_compose(ibuf, IMSG_PPP_STOP, 0, 0, -1, pktbuf,
22434682664Syasuoka 		    offsetof(struct npppd_who_list, entry[cnt])) == -1)
22534682664Syasuoka 			return (-1);
22634682664Syasuoka 
22734682664Syasuoka 		return (0);
22834682664Syasuoka 	}
22934682664Syasuoka 	if (_this->responding || _this->started_ppp_pos > 0) {
23034682664Syasuoka 		who_list = (struct npppd_who_list *)pktbuf;
23134682664Syasuoka 		who_list->more_data = 0;
23234682664Syasuoka 		for (cnt = 0, i = 0; i < _this->started_ppp_pos; i++) {
23334682664Syasuoka 			if (offsetof(struct npppd_who_list, entry[cnt + 1])
23434682664Syasuoka 			    > sizeof(pktbuf)) {
23534682664Syasuoka 				who_list->more_data = 1;
23634682664Syasuoka 				break;
23734682664Syasuoka 			}
23834682664Syasuoka 			if ((ppp = npppd_get_ppp_by_id(_this->npppd,
23934682664Syasuoka 			    _this->started_ppp[i])) == NULL)
24034682664Syasuoka 				/* may be disconnected */
24134682664Syasuoka 				continue;
24234682664Syasuoka 			npppd_who_init(&who_list->entry[cnt], ppp);
24334682664Syasuoka 			cnt++;
24434682664Syasuoka 		}
24534682664Syasuoka 		who_list->entry_count = cnt;
24634682664Syasuoka 		if (imsg_compose(ibuf, IMSG_PPP_START, 0, 0, -1, pktbuf,
24734682664Syasuoka 		    offsetof(struct npppd_who_list, entry[cnt])) == -1)
24834682664Syasuoka 			return (-1);
24934682664Syasuoka 
25034682664Syasuoka 		if (_this->started_ppp_pos > i)
25134682664Syasuoka 			memmove(&_this->started_ppp[0],
25234682664Syasuoka 			    &_this->started_ppp[i],
25334682664Syasuoka 			    sizeof(u_int) *
25434682664Syasuoka 				    (_this->started_ppp_pos - i));
25534682664Syasuoka 		_this->started_ppp_pos -= i;
25634682664Syasuoka 		if (who_list->more_data == 0)
25734682664Syasuoka 			_this->responding = false;
25834682664Syasuoka 		return (0);
25934682664Syasuoka 	}
26034682664Syasuoka 
26134682664Syasuoka 	return (0);
2620fbf3537Syasuoka }
2630fbf3537Syasuoka 
2640fbf3537Syasuoka static void
npppd_who_init(struct npppd_who * _this,npppd_ppp * ppp)26534682664Syasuoka npppd_who_init(struct npppd_who *_this, npppd_ppp *ppp)
2660fbf3537Syasuoka {
2670fbf3537Syasuoka 	struct timespec  curr_time;
2680fbf3537Syasuoka 	npppd_auth_base *realm = ppp->realm;
2690fbf3537Syasuoka 	npppd_iface     *iface = ppp_iface(ppp);
2700fbf3537Syasuoka 
271363e4d4bSyasuoka 	strlcpy(_this->username, ppp->username, sizeof(_this->username));
2720fbf3537Syasuoka 	_this->time = ppp->start_time;
27334682664Syasuoka 	clock_gettime(CLOCK_MONOTONIC, &curr_time);
2740fbf3537Syasuoka 	_this->duration_sec = curr_time.tv_sec - ppp->start_monotime;
275363e4d4bSyasuoka 	strlcpy(_this->tunnel_proto, npppd_ppp_tunnel_protocol_name(
276363e4d4bSyasuoka 	    ppp->pppd, ppp), sizeof(_this->tunnel_proto));
277363e4d4bSyasuoka 
278363e4d4bSyasuoka 	_this->tunnel_peer.peer_in4.sin_family = AF_UNSPEC;
2790fbf3537Syasuoka 	if (((struct sockaddr *)&ppp->phy_info)->sa_len > 0) {
280363e4d4bSyasuoka 		memcpy(&_this->tunnel_peer, &ppp->phy_info,
281dbad4650Sderaadt 		    MINIMUM(sizeof(_this->tunnel_peer),
282363e4d4bSyasuoka 			((struct sockaddr *)&ppp->phy_info)->sa_len));
2830fbf3537Syasuoka 	}
284363e4d4bSyasuoka 
2850fbf3537Syasuoka 	strlcpy(_this->ifname, iface->ifname, sizeof(_this->ifname));
28634682664Syasuoka 	if (realm == NULL)
28734682664Syasuoka 		_this->rlmname[0] = '\0';
28834682664Syasuoka 	else
2890fbf3537Syasuoka 		strlcpy(_this->rlmname, npppd_auth_get_name(realm),
2900fbf3537Syasuoka 		    sizeof(_this->rlmname));
2910fbf3537Syasuoka 
29234682664Syasuoka 	_this->framed_ip_address = ppp->acct_framed_ip_address;
2930fbf3537Syasuoka 	_this->ipackets = ppp->ipackets;
2940fbf3537Syasuoka 	_this->opackets = ppp->opackets;
2950fbf3537Syasuoka 	_this->ierrors = ppp->ierrors;
2960fbf3537Syasuoka 	_this->oerrors = ppp->oerrors;
2970fbf3537Syasuoka 	_this->ibytes = ppp->ibytes;
2980fbf3537Syasuoka 	_this->obytes = ppp->obytes;
299363e4d4bSyasuoka 	_this->ppp_id = ppp->id;
300*e83549beSgoda 	_this->mru = ppp->peer_mru;
3010fbf3537Syasuoka 
3020fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
3030fbf3537Syasuoka 	if (ppp->pipex_enabled != 0) {
3040fbf3537Syasuoka 		if (npppd_ppp_get_pipex_stat(_this, ppp) != 0) {
30534682664Syasuoka 			log_warn(
30634682664Syasuoka 			    "npppd_ppp_get_pipex_stat() failed in %s",
3070fbf3537Syasuoka 			    __func__);
3080fbf3537Syasuoka 		}
3090fbf3537Syasuoka 	}
3100fbf3537Syasuoka #endif
3110fbf3537Syasuoka }
3120fbf3537Syasuoka 
3130fbf3537Syasuoka #ifdef USE_NPPPD_PIPEX
3140fbf3537Syasuoka static int
npppd_ppp_get_pipex_stat(struct npppd_who * _this,npppd_ppp * ppp)3150fbf3537Syasuoka npppd_ppp_get_pipex_stat(struct npppd_who *_this, npppd_ppp *ppp)
3160fbf3537Syasuoka {
3170fbf3537Syasuoka 	npppd_iface                   *iface = ppp_iface(ppp);
3180fbf3537Syasuoka 	struct pipex_session_stat_req  req;
3190fbf3537Syasuoka #ifdef USE_NPPPD_PPPOE
3200fbf3537Syasuoka 	pppoe_session                 *pppoe;
3210fbf3537Syasuoka #endif
3220fbf3537Syasuoka #ifdef USE_NPPPD_PPTP
32334682664Syasuoka 	pptp_call                     *pptp;
3240fbf3537Syasuoka #endif
325886d2b78Syasuoka #ifdef USE_NPPPD_L2TP
326886d2b78Syasuoka 	l2tp_call                     *l2tp;
327886d2b78Syasuoka #endif
3280fbf3537Syasuoka 
3290fbf3537Syasuoka 	if (ppp->pipex_enabled == 0)
3300fbf3537Syasuoka 		return 0;
3310fbf3537Syasuoka 
3320fbf3537Syasuoka 	memset(&req, 0, sizeof(req));
3330fbf3537Syasuoka 	switch(ppp->tunnel_type) {
3340fbf3537Syasuoka #ifdef	USE_NPPPD_PPPOE
335821f7c56Syasuoka 	case NPPPD_TUNNEL_PPPOE:
3360fbf3537Syasuoka 		pppoe = (pppoe_session *)ppp->phy_context;
3370fbf3537Syasuoka 
338f0a4e295Syasuoka 		/* PPPOE specific information */
3390fbf3537Syasuoka 		req.psr_protocol = PIPEX_PROTO_PPPOE;
3400fbf3537Syasuoka 		req.psr_session_id = pppoe->session_id;
3410fbf3537Syasuoka 		break;
3420fbf3537Syasuoka #endif
3430fbf3537Syasuoka #ifdef	USE_NPPPD_PPTP
344821f7c56Syasuoka 	case NPPPD_TUNNEL_PPTP:
34534682664Syasuoka 		pptp = (pptp_call *)ppp->phy_context;
3460fbf3537Syasuoka 
347f0a4e295Syasuoka 		/* PPTP specific information */
34834682664Syasuoka 		req.psr_session_id = pptp->id;
3490fbf3537Syasuoka 		req.psr_protocol = PIPEX_PROTO_PPTP;
3500fbf3537Syasuoka 		break;
3510fbf3537Syasuoka #endif
352886d2b78Syasuoka #ifdef USE_NPPPD_L2TP
353821f7c56Syasuoka 	case NPPPD_TUNNEL_L2TP:
354886d2b78Syasuoka 		l2tp = (l2tp_call *)ppp->phy_context;
355886d2b78Syasuoka 
356886d2b78Syasuoka 		/* L2TP specific information */
357886d2b78Syasuoka 		req.psr_session_id = l2tp->session_id;
358886d2b78Syasuoka 		req.psr_protocol = PIPEX_PROTO_L2TP;
359886d2b78Syasuoka 		break;
360886d2b78Syasuoka #endif
3610fbf3537Syasuoka 	default:
3620fbf3537Syasuoka 		errno = EINVAL;
3630fbf3537Syasuoka 		return 1;
3640fbf3537Syasuoka 	}
3650fbf3537Syasuoka 
366f0a4e295Syasuoka 	/* update statistics in kernel */
3670fbf3537Syasuoka 	if (ioctl(iface->devf, PIPEXGSTAT, &req) != 0)
3680fbf3537Syasuoka 		return 1;
3690fbf3537Syasuoka 
3700fbf3537Syasuoka 	_this->ipackets += req.psr_stat.ipackets;
3710fbf3537Syasuoka 	_this->opackets += req.psr_stat.opackets;
3720fbf3537Syasuoka 	_this->ierrors += req.psr_stat.ierrors;
3730fbf3537Syasuoka 	_this->oerrors += req.psr_stat.oerrors;
3740fbf3537Syasuoka 	_this->ibytes += req.psr_stat.ibytes;
3750fbf3537Syasuoka 	_this->obytes += req.psr_stat.obytes;
3760fbf3537Syasuoka 
3770fbf3537Syasuoka 	return 0;
3780fbf3537Syasuoka }
3790fbf3537Syasuoka #endif
380