1
0
This repository has been archived on 2024-07-22. You can view files and clone it, but cannot push or open issues or pull requests.
Files
2024-07-22 01:58:46 -03:00

784 lines
26 KiB
C
Executable File

#include <stdio.h>
#include <unistd.h>
#include <time.h> /* for time() */
#include <fcntl.h>
#include <string.h> /* for strerror() */
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/param.h> /* for OPEN_MAX */
#if __GLIBC__ >= 2
#include <sys/poll.h>
#else /* ugly hack to make it compile on RH 4.2 - WA */
#include <syscall.h>
#include <linux/poll.h>
#define SYS_poll 168
_syscall3(int,poll,struct pollfd *,ufds,unsigned int,nfds,int,timeout);
#endif
#include <atm.h>
#include <linux/atmioc.h>
#include <linux/atmmpc.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <atm.h>
#include <netinet/in.h> /* for ntohl() */
#include "packets.h"
#include "k_interf.h"
#include "io.h"
#include "get_vars.h"
#ifdef BROKEN_POLL
#include "poll2select.h"
#endif
#define POLL_TIMEOUT 5000 /* poll() timeout, 5 seconds */
#if 1
#define dprintf printf
#else
#define dprintf(format,args...)
#endif
#if 0
#define ddprintf printf
#else
#define ddprintf(format,args...)
#endif
extern struct mpc_control mpc_control; /* from main.c */
int keep_alive_sm_running = 0;
struct outgoing_shortcut {
int fd;
uint32_t ipaddr; /* in network byte order */
int state; /* see io.h for states */
};
static struct llc_snap_hdr llc_snap_mpoa_ctrl = {
0xaa, 0xaa, 0x03,
{0x00, 0x00, 0x5e},
{0x00, 0x03}
};
static time_t stay_alive; /* Next Keep-Alive should come before we hit this time */
static struct pollfd fds[OPEN_MAX];
static int first_empty; /* first non-reserved slot in fds[] */
static int fds_used; /* first non-occupied slot in fds[], => also # of used fds */
static short socket_type[OPEN_MAX]; /* type and state info for fds[], see "io.h" for types */
static struct outgoing_shortcut ingress_shortcuts[OPEN_MAX]; /* array of shortcuts we made */
static int update_ingress_entry(uint32_t *addr, int fd, int new_state);
static int msg_from_mps(int slot);
static int accept_conn(int slot);
static int add_shortcut(int slot, int type);
static int check_connection(int slot);
static int complete_connection(int slot);
static int create_shortcut(char *atm_addr,struct atm_qos qos);
static void wait_for_mps_ctrl_addr(void);
static int connect_to_MPS(void);
void main_loop(int listen_socket)
{
int i, changed_fds;
int kernel_ok, mps_ok, new_ctrl, new_shortcut;
int poll_timeout = POLL_TIMEOUT;
time_t now, previous_now;
for (i = 0; i < OPEN_MAX; i++)
fds[i].fd = -1;
fds[0].fd = mpc_control.kernel_socket; /* mpcd <--> kernel socket */
fds[0].events = POLLIN;
socket_type[0]= KERNEL;
if(!mpc_control.mps_ctrl_addr_set) /* Can't do much without the MPS control ATM addr */
wait_for_mps_ctrl_addr();
connect_to_MPS();
fds[1].fd = mpc_control.MPS_socket; /* we opened this to MPS */
fds[1].events = POLLIN;
socket_type[1]= (OUTGOING_CTRL | CONNECTED);
fds[2].fd = mpc_control.MPS_listen_socket; /* for incoming control calls */
fds[2].events = POLLIN;
socket_type[2]= LISTENING_CTRL;
fds[3].fd = listen_socket; /* for incoming shortcuts */
fds[3].events = POLLIN;
socket_type[3]= LISTENING_DATA;
fds_used = first_empty = 4;
now = previous_now = time(NULL);
while (1) {
kernel_ok = mps_ok = new_ctrl = new_shortcut = 1;
fflush(stdout);
#ifdef BROKEN_POLL
changed_fds = poll2select(fds, fds_used, poll_timeout);
#else
changed_fds = poll(fds, fds_used, poll_timeout);
#endif
#if 0
printf("\nio.c: main_loop() poll returns %d\n", changed_fds);
for (i = 0; i < OPEN_MAX; i++) {
if (fds[i].fd < 0 ) continue; /* slot not in use */
if ( fds[i].revents == 0) {
printf("check1: fd %d slot %d not changed\n", fds[i].fd, i);
}
else printf("check1: fd %d slot %d changed\n", fds[i].fd, i);
}
#endif
switch(changed_fds) {
case -1:
printf("mpcd: io.c: main_loop: poll error: %s\n", strerror(errno));
if(errno == EINTR) continue;
goto out; /* return to main() */
break; /* not reached */
case 0:
keep_alive_sm(0, -1); /* (keepalive_liftime, seq_num) */
clear_expired(); /* id_list.c */
poll_timeout = POLL_TIMEOUT;
previous_now = time(NULL);
continue;
break; /* not reached */
}
/* It was not a timeout. Adjust poll_timeout */
now = time(NULL);
poll_timeout -= now - previous_now;
if (poll_timeout < 0) poll_timeout = 0;
/* Since we are here something happened to the fds */
if (fds[0].revents) {
dprintf("mpcd: io.c: main_loop() msg_from_kernel\n");
kernel_ok = msg_from_kernel(fds[0].fd);
changed_fds--;
}
if (fds[1].revents) {
ddprintf("mpcd: io.c: main_loop() msg_from_mps1\n");
mps_ok = msg_from_mps(1);
changed_fds--;
}
if (fds[2].revents) {
new_ctrl = accept_conn(2);
changed_fds--;
if( new_ctrl < 0 )
break;
socket_type[new_ctrl] = INCOMING_CTRL | CONNECTED;
dprintf("mpcd: io.c main_loop() accepted INCOMING_CTRL slot %d\n", new_ctrl);
}
if (fds[3].revents) {
new_shortcut = accept_conn(3);
dprintf("mpcd: io.c main_loop() accepted INCOMING_SHORTCUT slot %d\n", new_shortcut);
changed_fds--;
if( new_shortcut < 0 )
break;
socket_type[new_shortcut] = INCOMING_SHORTCUT;
if (add_shortcut(new_shortcut, MPC_SOCKET_EGRESS) < 0)
break;
}
#if 0
if (changed_fds == 0) /* see if we can already go back to poll() */
continue;
#endif
for (i = first_empty; i < fds_used; i++) {
if (fds[i].fd < 0 ) continue; /* slot not in use */
if ( fds[i].revents == 0) {
ddprintf("fd %d slot %d not changed\n", fds[i].fd, i);
continue;
}
ddprintf("about to process fd %d slot %d\n", fds[i].fd, i);
if (socket_type[i] & INCOMING_CTRL) {
ddprintf("mpcd: io.c: main_loop() msg_from_mps2\n");
mps_ok = msg_from_mps(i);
}
else {
ddprintf("mpcd: io.c: main_loop() checking connection fd %d\n", fds[i].fd);
if (check_connection(i) < 0) {
printf("mpcd: io.c: main_loop: check_connection returned < 0\n");
break; /* this will cause break from while(1) too */
}
}
if (--changed_fds == 0) break; /* no more changed fds, leave for() */
}
if (changed_fds != 0){
printf("mpcd: changed_fds = %d\n", changed_fds);
/* break; */ /* leave while(1) */
}
if (kernel_ok && mps_ok >= 0 && new_ctrl >= 0 && new_shortcut >= 0)
continue; /* back to poll() */
else break; /* leave main_loop */
}
out:
/* clean up, close the sockets */
for (i = 0; i < fds_used; i++) {
if (fds[i].fd < 0)
continue;
close(fds[i].fd);
socket_type[i] = NOT_USED;
}
printf("mpcd: io.c: exiting main_loop()\n");
return;
}
/*
* If MPS control ATM address is not given as an argument this func waits until
* kernel has found one from a TLV in le_arp and tells us what it is.
*/
static void wait_for_mps_ctrl_addr(){
while(!mpc_control.mps_ctrl_addr_set){
#ifdef BROKEN_POLL
if(poll2select(fds, 1, -1))
#else
if(poll(fds, 1, -1))
#endif
msg_from_kernel(fds[0].fd);
}
return;
}
/*
* Sends a packet to MPS. Adds LLC/SNAP encapsulation
* in the beginning of the buffer.
*/
int send_to_mps(char *buff, int length)
{
char tmp[MAX_PACKET_LENGTH + sizeof(struct llc_snap_hdr)];
int bytes_written;
char *pos = tmp;
if(mpc_control.MPS_socket<0){
connect_to_MPS();
fds[1].fd = mpc_control.MPS_socket;
fds[1].events = POLLIN;
fds[1].revents = 0;
socket_type[1] = (OUTGOING_CTRL | CONNECTED);
}
memcpy(pos, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr));
pos += sizeof(struct llc_snap_hdr);
memcpy(pos, buff, length);
length += sizeof(struct llc_snap_hdr);
bytes_written = write(mpc_control.MPS_socket, tmp, length);
while(bytes_written != 0){
bytes_written = write(mpc_control.MPS_socket, tmp+bytes_written, length-bytes_written);
if( bytes_written < 0 ){
printf("mpcd: io.c: send_to_mps() write failed\n");
return -1;
}
}
return 1;
}
/*
* Sends a control packet over a shortcut. Used in a dataplane purge.
*/
int send_to_dataplane(char *buff, int length, int shortcut_fd)
{
char tmp[MAX_PACKET_LENGTH + sizeof(struct llc_snap_hdr)];
int bytes_written;
char *pos = tmp;
memcpy(pos, &llc_snap_mpoa_ctrl, sizeof(struct llc_snap_hdr));
pos += sizeof(struct llc_snap_hdr);
memcpy(pos, buff, length);
length += sizeof(struct llc_snap_hdr);
bytes_written = write(shortcut_fd, tmp, length);
while(bytes_written != 0){
bytes_written = write(shortcut_fd, tmp+bytes_written, length-bytes_written);
if( bytes_written < 0 ){
printf("mpcd: io.c: write to dataplane failed\n");
return -1;
}
}
return 1;
}
/*
* Keep alive state machine. Sequence number less than
* and keep_alive_lifetime equal to zero is used
* when checking wheter the MPS is still alive.
*
*/
void keep_alive_sm(unsigned keep_alive_lifetime, int sequence_number){
struct k_message msg;
static unsigned previous_sequence_number = 0;
static int start_keep_alive_sm = 0;
time_t now = time(NULL);
memset(&msg,0,sizeof(struct k_message));
if(!keep_alive_sm_running){
start_keep_alive_sm = 0;
return;
}
if(!start_keep_alive_sm){
dprintf("mpcd: io.c: starting keep_alive_sm.\n");
stay_alive = time(NULL) + MPC_C2;
start_keep_alive_sm = 1;
return;
}
if( now > stay_alive ){
dprintf("mpcd: io.c: MPS death!");
msg.type = MPS_DEATH;
memcpy(msg.MPS_ctrl,mpc_control.MPS_CTRL_ATM_ADDR,ATM_ESA_LEN);
send_to_kernel(&msg);
previous_sequence_number = 0;
stay_alive = now + MPC_C2;
return;
}
if( sequence_number < 0 )
return;
if( sequence_number < previous_sequence_number ){
dprintf("mpcd: io.c: MPS death!");
msg.type = MPS_DEATH;
memcpy(msg.MPS_ctrl,mpc_control.MPS_CTRL_ATM_ADDR,ATM_ESA_LEN);
send_to_kernel(&msg);
previous_sequence_number = 0;
stay_alive = now + MPC_C2;
return;
}
stay_alive = now + keep_alive_lifetime;
previous_sequence_number = sequence_number;
return;
}
/*
* Creates a socket, sets traffic and sap parameters
* and binds the socket with given address.
*
* returns < 0 for error, socket for ok
*/
int get_socket(struct sockaddr_atmsvc *address)
{
struct atm_qos qos;
struct atm_sap sap;
int socket_fd;
socket_fd = socket(PF_ATMSVC, SOCK_DGRAM, 0);
if( socket_fd < 0 ){
printf("mpcd: io.c: socket creation failure: %s \n",strerror(errno));
return -1;
}
memset(&qos, 0, sizeof(qos));
memset(&sap, 0, sizeof(sap));
qos.aal = ATM_AAL5;
qos.txtp.traffic_class = ATM_UBR;
qos.rxtp.traffic_class = ATM_UBR;
qos.txtp.max_sdu = 1536;
qos.rxtp.max_sdu = 1536;
sap.blli[0].l2_proto = ATM_L2_ISO8802;
if (setsockopt(socket_fd, SOL_ATM,SO_ATMQOS, &qos, sizeof(qos)) < 0){
printf("mpcd: io.c: setsockopt SO_ATMQOS failed: %s \n",strerror(errno));
close(socket_fd);
return -1;
}
if (setsockopt(socket_fd,SOL_ATM,SO_ATMSAP,&sap,sizeof(sap)) < 0) {
printf("mpcd: io.c: setsockop SO_ATMSAP failed\n");
close (socket_fd);
return -1;
}
if (address == NULL)
return socket_fd;
if (bind(socket_fd, (struct sockaddr *)address, sizeof(struct sockaddr_atmsvc)) < 0){
printf("mpcd: io.c: bind failure: %s \n",strerror(errno));
close(socket_fd);
return -1;
}
return socket_fd;
}
/*
* Creates an ATM_ANYCLASS traffic class socket, sets traffic and sap
* parameters and binds the socket with given address.
*
* returns < 0 for error, socket for ok
*/
int get_listen_socket(struct sockaddr_atmsvc *address)
{
int s;
struct atm_qos qos;
s = get_socket(NULL);
if (s < 0) {
printf("mpcd: io.c: get_listen_socket() get socket failed\n");
return s;
}
memset(&qos, 0, sizeof(qos));
qos.aal = ATM_AAL5;
qos.txtp.traffic_class = ATM_ANYCLASS;
qos.rxtp.traffic_class = ATM_ANYCLASS;
if (setsockopt(s, SOL_ATM,SO_ATMQOS, &qos, sizeof(qos)) < 0){
printf("mpcd: io.c: get_listen_socket() setsockopt SO_ATMQOS: %s\n",
strerror(errno));
close(s);
return -1;
}
if (bind(s, (struct sockaddr *)address, sizeof(struct sockaddr_atmsvc)) < 0){
printf("mpcd: io.c: get_listen_socket() bind: %s\n", strerror(errno));
close(s);
return -1;
}
if (listen(s, 5) < 0) {
printf("mpcd: io.c: get_lilsten_socket() listen: %s\n", strerror(errno));
close(s);
return -1;
}
return s;
}
/*
* If addr != NULL searches by addr. If addr == NULL searches by fd.
* Returns ipaddr.
*
*/
static int update_ingress_entry(uint32_t *addr, int fd, int new_state)
{
int i;
if (addr != NULL) {
dprintf("mpcd: io.c update_ingress_entry() updating ip 0x%x\n", *addr);
for (i = 0; i < OPEN_MAX; i++)
if (ingress_shortcuts[i].ipaddr == *addr)
break;
}
else {
dprintf("mpcd: io.c update_ingress_entry() updating fd %d\n", fd);
for (i = 0; i < OPEN_MAX; i++)
if (ingress_shortcuts[i].fd == fd)
break;
}
if (i == OPEN_MAX) {
printf("mpcd: io.c: update_ingress_entry: entry not found\n");
return 0;
}
ingress_shortcuts[i].fd = fd;
ingress_shortcuts[i].state = new_state;
if (new_state == INGRESS_NOT_USED)
memset(&ingress_shortcuts[i], 0 , sizeof(ingress_shortcuts[i]));
return ingress_shortcuts[i].ipaddr;
}
/*
* returns < 0 for error
*
*/
static int msg_from_mps(int slot)
{
int bytes_read, fd;
char buff[MAX_PACKET_LENGTH];
fd = fds[slot].fd;
bytes_read = read(fd, buff, sizeof(buff));
if (bytes_read < 0) {
printf("mpcd: io.c: read failed from MPS: %s\n", strerror(errno));
close(fd);
fds[slot].fd = -1;
socket_type[slot] = NOT_USED;
return -1;
}
if (bytes_read == 0) {
dprintf("mpcd: io.c: EOF from MPS\n");
close(fd);
fds[slot].fd = -1;
if (slot == 1)
mpc_control.MPS_socket = -1;
socket_type[slot] = NOT_USED;
return 1; /* See spec 4.6. Might be normal */
}
if ( memcmp(buff, &llc_snap_mpoa_ctrl, sizeof(llc_snap_mpoa_ctrl)) != 0 ) {
printf("mpcd: io.c: msg_from_mps: MPS is pushing us garbage\n");
return -1;
}
(void)recognize_packet(buff + sizeof(struct llc_snap_hdr));
return 0;
}
/*
* returns < 0 for error, slot of the new socket for ok
*
*/
static int accept_conn(int slot)
{
struct sockaddr_atmsvc sa;
int i, new_fd, sa_len;
sa_len = sizeof(sa);
new_fd = accept(fds[slot].fd, (struct sockaddr *)&sa, &sa_len);
if (new_fd < 0) {
printf("mpcd: io.c: accept_conn: %s\n", strerror(errno));
return -1;
}
for (i = first_empty; i < OPEN_MAX; i++) {
if (fds[i].fd >= 0) /* slot in use ? */
continue;
fds[i].fd = new_fd;
fds[i].events = POLLIN;
fds[i].revents = 0;
break;
}
if (i == OPEN_MAX) {
printf("mpcd: io.c: accept_conn: no room for new connection\n");
return -1;
}
if (i >= fds_used)
fds_used = i + 1;
return i;
}
/*
* returns < 0 for error, slot of the new socket for ok
*
*/
static int add_shortcut(int slot, int type)
{
struct atmmpc_ioc ioc_data;
int ipaddr = 0;
if (type == MPC_SOCKET_INGRESS)
ipaddr = update_ingress_entry(NULL, fds[slot].fd, INGRESS_CONNECTED);
ioc_data.dev_num = mpc_control.INTERFACE_NUMBER;
ioc_data.ipaddr = ipaddr;
ioc_data.type = type;
if (ioctl(fds[slot].fd, ATMMPC_DATA, &ioc_data) < 0) {
printf("mpcd: io.c: add_shortcut: %s\n", strerror(errno));
close(fds[slot].fd);
fds[slot].fd = -1;
socket_type[slot] = NOT_USED;
return -1;
}
return slot;
}
/*
* ECONNRESET == RST in TCP world. Check what equivalent
* events can happen in ATM world.
*
* Returns < 0 for error
*/
static int check_connection(int slot)
{
char buff[MAX_PACKET_LENGTH];
struct k_message *msg;
struct pollfd *pfd;
int bytes_read;
dprintf("mpcd: io.c: check_connection() event in fd %d, type %d\n", fds[slot].fd, socket_type[slot]);
if (socket_type[slot] & CONNECTING) { /* connect() completed (maybe) */
complete_connection(slot); /* ignore return value */
return 0;
}
pfd = &fds[slot];
bytes_read = read(pfd->fd, buff, sizeof(buff));
if (bytes_read < 0) {
if (errno == ECONNRESET || errno == EPIPE) { /* conn reset by the other end or kernel (EPIPE) */
if (socket_type[slot] & OUTGOING_SHORTCUT)
update_ingress_entry(NULL, pfd->fd, INGRESS_NOT_USED);
close(pfd->fd);
pfd->fd = -1;
socket_type[slot] = NOT_USED;
return 1;
}
printf("mpcd: io.c: check_connection() bytes_read=%d, errno='%s'\n", bytes_read, strerror(errno));
return -1;
}
if (bytes_read == 0) { /* conn closed by the other end */
if (socket_type[slot] & OUTGOING_SHORTCUT)
update_ingress_entry(NULL, pfd->fd, INGRESS_NOT_USED);
dprintf("mpcd: io.c: check_connection() fd %d type %d; connection closed'\n", pfd->fd, socket_type[slot]);
close(pfd->fd);
pfd->fd = -1;
socket_type[slot] = NOT_USED;
return 1;
}
/* See if this is a MPOA control packet */
if ( memcmp(buff, &llc_snap_mpoa_ctrl, sizeof(llc_snap_mpoa_ctrl)) == 0 )
if ( recognize_packet(buff + sizeof(llc_snap_mpoa_ctrl)) >= 0)
return 1;
dprintf("mpcd: io.c check_connection(): msg from kernel\n");
msg = (struct k_message *)buff;
if(msg->type == DATA_PLANE_PURGE){
send_purge_request(msg->content.eg_info.mps_ip,32,
get_own_ip_addr(mpc_control.INTERFACE_NUMBER),pfd->fd);
return 1;
}
printf("mpcd: io.c check_connection(): unknown msg %d from kernel, ignoring",
msg->type);
return 1;
}
/*
* returns < 0 for unsuccessful connect, fd for ok
*
*/
static int complete_connection(int slot)
{
int retval;
struct sockaddr_atmsvc dummy;
dprintf("mpcd: io.c: complete_connection() completing fd %d slot %d\n", fds[slot].fd, slot);
/* this seems to be common method in Linux-ATM
* making sure that nonblocking connect was
* completed successfully
*/
retval = connect(fds[slot].fd,(struct sockaddr *)&dummy, sizeof(dummy));
if (retval < 0) {
printf("mpcd: io.c: complete_connection(): '%s'\n", strerror(errno));
socket_type[slot] = NOT_USED;
update_ingress_entry(NULL, fds[slot].fd, INGRESS_NOT_USED);
close(fds[slot].fd);
fds[slot].fd = -1;
fds[slot].revents = 0;
return 0;
}
socket_type[slot] &= ~CONNECTING;
socket_type[slot] |= CONNECTED;
fds[slot].events = POLLIN; /* We left POLLOUT accidentally in. Hope you never do the same */
fds[slot].revents = 0;
if(socket_type[slot] & OUTGOING_SHORTCUT)
return add_shortcut(slot, MPC_SOCKET_INGRESS);
return fds[slot].fd;
}
/*
* Called if kernel wants us to create a shortcut
*/
void create_ingress_svc(uint32_t ipaddr, char *atm_addr, struct atm_qos qos)
{
int i, new_socket;
new_socket = create_shortcut(atm_addr,qos);
if (new_socket < 0) {
printf("mpcd: io.c: create_ingress_svc: create_shortcut failed\n");
return;
}
for (i = first_empty; i < OPEN_MAX; i++) {
if (fds[i].fd >= 0) /* slot in use ? */
continue;
fds[i].fd = new_socket;
fds[i].events = POLLIN | POLLOUT;
fds[i].revents = 0;
break;
}
if (i == OPEN_MAX) {
printf("mpcd: io.c: create_ingress_svc: create_shortcut: no room for new connection\n");
return;
}
socket_type[i] = (OUTGOING_SHORTCUT | CONNECTING);
if (i >= fds_used)
fds_used = i + 1;
/* Store the IP address we are creating this shortcut for */
dprintf("mpcd: io.c: create_ingress_svc: adding ip 0x%x\n", ipaddr);
for(i = 0; i < OPEN_MAX; i++)
if (ingress_shortcuts[i].state == INGRESS_NOT_USED)
break;
if (i == OPEN_MAX) {
printf("mpcd: io.c: create_ingress_svc: ingress no more entries\n");
return;
}
ingress_shortcuts[i].fd = new_socket;
ingress_shortcuts[i].ipaddr = ipaddr;
ingress_shortcuts[i].state = INGRESS_CONNECTING;
}
/*
* returns < 0 for error, socket for ok
*
*/
static int create_shortcut(char *atm_addr, struct atm_qos qos)
{
int s, flags, retval;
struct sockaddr_atmsvc addr;
dprintf("mpcd: io.c: create_shortcut() addr = 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x\n",
atm_addr[0], atm_addr[1], atm_addr[2], atm_addr[3], atm_addr[4]);
memset(&addr, 0, sizeof(addr));
addr.sas_family = AF_ATMSVC;
memcpy(addr.sas_addr.prv, atm_addr, ATM_ESA_LEN);
s = get_socket(&mpc_control.data_listen_addr);
if(qos.txtp.traffic_class > ATM_UBR || qos.rxtp.traffic_class > ATM_UBR){
printf("mpcd: io.c: create_shortcut() setting qos params (cbr)\n");
if (setsockopt(s, SOL_ATM,SO_ATMQOS, &qos, sizeof(qos)) < 0){
printf("mpcd: io.c: setsockopt SO_ATMQOS failed: %s \n",strerror(errno));
close(s);
return -1;
}
}
dprintf("mpcd: create_shortcut() got fd %d \n", s);
if ( (flags = fcntl(s, F_GETFL)) < 0) {
printf("mpcd: io.c: fcntl(F_GETFL) failed: %s\n", strerror(errno));
close(s);
return -1;
}
if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
printf("mpcd: io.c: fcntl(F_SETFL) failed: %s\n", strerror(errno));
close(s);
return -1;
}
retval = connect(s, (struct sockaddr *)&addr, sizeof(addr));
if (retval < 0 && errno != EINPROGRESS) {
printf("mpcd: io.c: create_shortcut: connect failed: %s\n", strerror(errno));
return -1;
}
return s;
}
/*
* Creates an active connection to MPS
*
* returns < 0 for error
*/
static int connect_to_MPS(){
int c;
struct sockaddr_atmsvc mps_ctrl_addr;
struct sockaddr_atmsvc ctrl_listen_addr;
memset(&mps_ctrl_addr,0,sizeof(struct sockaddr_atmsvc));
memset(&ctrl_listen_addr,0,sizeof(struct sockaddr_atmsvc));
memcpy(mps_ctrl_addr.sas_addr.prv,mpc_control.MPS_CTRL_ATM_ADDR,ATM_ESA_LEN);
memcpy(ctrl_listen_addr.sas_addr.prv,mpc_control.OWN_ATM_ADDRESS,ATM_ESA_LEN);
mps_ctrl_addr.sas_family = AF_ATMSVC;
ctrl_listen_addr.sas_family = AF_ATMSVC;
mpc_control.MPS_socket = get_socket(&ctrl_listen_addr);
if (mpc_control.MPS_socket < 0)
return -1;
c = connect(mpc_control.MPS_socket, (struct sockaddr *)&(mps_ctrl_addr),
sizeof(struct sockaddr_atmsvc));
if( c < 0 ){
printf("mpcd: io.c: connect to MPS failed: %s \n",strerror(errno));
close(mpc_control.MPS_socket);
return -1;
}
return 0;
}