1144564Simp/*-
21558Srgrimes * SPDX-License-Identifier: BSD-2-Clause
31558Srgrimes *
41558Srgrimes * Copyright (C) 2011 Hiroki Sato <hrs@FreeBSD.org>
51558Srgrimes * All rights reserved.
61558Srgrimes *
71558Srgrimes * Redistribution and use in source and binary forms, with or without
81558Srgrimes * modification, are permitted provided that the following conditions
91558Srgrimes * are met:
101558Srgrimes * 1. Redistributions of source code must retain the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer.
121558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
131558Srgrimes *    notice, this list of conditions and the following disclaimer in the
141558Srgrimes *    documentation and/or other materials provided with the distribution.
151558Srgrimes *
161558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
171558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
191558Srgrimes * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS
201558Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
211558Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
221558Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
231558Srgrimes * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
241558Srgrimes * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
251558Srgrimes * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
261558Srgrimes * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
271558Srgrimes *
281558Srgrimes */
291558Srgrimes
301558Srgrimes#include <sys/queue.h>
311558Srgrimes#include <sys/types.h>
321558Srgrimes#include <sys/socket.h>
331558Srgrimes#include <sys/stat.h>
3423669Speter#include <sys/un.h>
3596707Strhodes#include <sys/uio.h>
361558Srgrimes#include <net/if.h>
371558Srgrimes#include <net/if_dl.h>
381558Srgrimes#include <netinet/in.h>
391558Srgrimes#include <netinet/icmp6.h>
401558Srgrimes#include <fcntl.h>
411558Srgrimes#include <errno.h>
421558Srgrimes#include <netdb.h>
43164911Sdwmalone#include <unistd.h>
44204111Suqs#include <signal.h>
451558Srgrimes#include <string.h>
461558Srgrimes#include <stdarg.h>
4735852Sjkh#include <stdio.h>
481558Srgrimes#include <stdlib.h>
491558Srgrimes#include <syslog.h>
501558Srgrimes
511558Srgrimes#include "pathnames.h"
521558Srgrimes#include "rtadvd.h"
531558Srgrimes#include "if.h"
5423669Speter#include "control.h"
55102231Strhodes#include "control_client.h"
561558Srgrimes
571558Srgrimesint
581558Srgrimescm_handler_client(int fd, int state, char *buf_orig)
591558Srgrimes{
601558Srgrimes	char buf[CM_MSG_MAXLEN];
611558Srgrimes	struct ctrl_msg_hdr *cm;
621558Srgrimes	struct ctrl_msg_hdr *cm_orig;
631558Srgrimes	int error;
64144099Simp	char *msg;
651558Srgrimes	char *msg_orig;
661558Srgrimes
67102231Strhodes	syslog(LOG_DEBUG, "<%s> enter", __func__);
681558Srgrimes
691558Srgrimes	memset(buf, 0, sizeof(buf));
701558Srgrimes	cm = (struct ctrl_msg_hdr *)buf;
711558Srgrimes	cm_orig = (struct ctrl_msg_hdr *)buf_orig;
721558Srgrimes	msg = (char *)buf + sizeof(*cm);
731558Srgrimes	msg_orig = (char *)buf_orig + sizeof(*cm_orig);
741558Srgrimes
751558Srgrimes	if (cm_orig->cm_len > CM_MSG_MAXLEN) {
761558Srgrimes		syslog(LOG_DEBUG, "<%s> msg too long", __func__);
771558Srgrimes		close(fd);
781558Srgrimes		return (-1);
791558Srgrimes	}
801558Srgrimes	cm->cm_type = cm_orig->cm_type;
811558Srgrimes	if (cm_orig->cm_len > sizeof(*cm_orig)) {
821558Srgrimes		memcpy(msg, msg_orig, cm_orig->cm_len - sizeof(*cm));
831558Srgrimes		cm->cm_len = cm_orig->cm_len;
841558Srgrimes	}
851558Srgrimes	while (state != CM_STATE_EOM) {
861558Srgrimes		syslog(LOG_DEBUG, "<%s> state = %d", __func__, state);
871558Srgrimes
881558Srgrimes		switch (state) {
891558Srgrimes		case CM_STATE_INIT:
901558Srgrimes			state = CM_STATE_EOM;
911558Srgrimes			break;
921558Srgrimes		case CM_STATE_MSG_DISPATCH:
931558Srgrimes			cm->cm_version = CM_VERSION;
941558Srgrimes			error = cm_send(fd, buf);
951558Srgrimes			if (error) {
961558Srgrimes				syslog(LOG_WARNING,
971558Srgrimes				    "<%s> cm_send()", __func__);
981558Srgrimes				return (-1);
991558Srgrimes			}
1001558Srgrimes			state = CM_STATE_ACK_WAIT;
1011558Srgrimes			break;
1021558Srgrimes		case CM_STATE_ACK_WAIT:
1031558Srgrimes			error = cm_recv(fd, buf);
1041558Srgrimes			if (error) {
10598542Smckusick				syslog(LOG_ERR,
10698542Smckusick				    "<%s> cm_recv()", __func__);
10798542Smckusick				close(fd);
10898542Smckusick				return (-1);
10998542Smckusick			}
11098542Smckusick			switch (cm->cm_type) {
11198542Smckusick			case CM_TYPE_ACK:
11298542Smckusick				syslog(LOG_DEBUG,
11398542Smckusick				    "<%s> CM_TYPE_ACK", __func__);
114100207Smckusick				break;
11598542Smckusick			case CM_TYPE_ERR:
11698542Smckusick				syslog(LOG_DEBUG,
117100207Smckusick				    "<%s> CM_TYPE_ERR", __func__);
118167011Smckusick				close(fd);
11998542Smckusick				return (-1);
1201558Srgrimes			default:
1211558Srgrimes				syslog(LOG_DEBUG,
1221558Srgrimes				    "<%s> unknown status", __func__);
1231558Srgrimes				close(fd);
1241558Srgrimes				return (-1);
1251558Srgrimes			}
1261558Srgrimes			memcpy(buf_orig, buf, cm->cm_len);
1271558Srgrimes			state = CM_STATE_EOM;
1281558Srgrimes			break;
1291558Srgrimes		}
1301558Srgrimes	}
1311558Srgrimes	close(fd);
1321558Srgrimes	return (0);
1331558Srgrimes}
1341558Srgrimes