summaryrefslogtreecommitdiffstats
path: root/cpukit/pppd/rtemspppd.c
blob: 0089c01946afd34e0d35a092806f904ce7e87ead (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210

#include <rtems.h>
#include <rtems/rtems_bsdnet.h>
#include "pppd.h"
#include "rtemspppd.h"


/* define pppd function prototypes */
extern void pppasyncattach(void);
extern int  pppdmain(int, char **);

/* define global variables */
rtems_id                   rtems_pppd_taskid;
rtems_pppd_hookfunction    rtems_pppd_errorfp;
rtems_pppd_hookfunction    rtems_pppd_exitfp;


static rtems_task pppTask(rtems_task_argument arg)
{
  rtems_status_code   sc = RTEMS_SUCCESSFUL;
  rtems_option        options;
  rtems_event_set     in;
  rtems_event_set     out;
  int                 iStatus;

  /* call function to setup ppp line discipline */
  pppasyncattach();

  /* enter processing loop */
  in      = (RTEMS_EVENT_29 | RTEMS_EVENT_30);
  options = (RTEMS_EVENT_ANY | RTEMS_WAIT);
  while ( sc == RTEMS_SUCCESSFUL ) {
    /* wait for the next event */
    sc = rtems_event_receive(in, options, RTEMS_NO_TIMEOUT, &out);
    if ( sc == RTEMS_SUCCESSFUL ) {
      /* determine which event was sent */
      if ( out & RTEMS_EVENT_29 ) {
        /* terminate event received */
        /* set value to break out of event loop */
        sc = RTEMS_UNSATISFIED;
      }
      else if ( out & RTEMS_EVENT_30 ) {
        /* connect request */
        /* execute the pppd main code */
        iStatus = pppdmain(0, NULL);
        if ( iStatus == EXIT_OK ) {
          /* check exit callback */
          if ( rtems_pppd_exitfp ) {
            (*rtems_pppd_exitfp)();
          }
        }
        else {
          /* check error callback */
          if ( rtems_pppd_errorfp ) {
            (*rtems_pppd_errorfp)();
          }
        }
      }
    }
  }

  /* terminate myself */
  rtems_pppd_taskid = 0;
  rtems_task_delete(RTEMS_SELF);
}

int rtems_pppd_initialize(void)
{
  int                 iReturn  = (int)-1;
  rtems_unsigned32    priority = 100;
  rtems_status_code   status;
  rtems_name          taskName;

  /* determine priority value */
  if ( rtems_bsdnet_config.network_task_priority ) {
    priority = rtems_bsdnet_config.network_task_priority;
  }

  /* initialize the exit hook */
  rtems_pppd_exitfp = (rtems_pppd_hookfunction)0;

  /* create the rtems task */
  taskName = rtems_build_name( 'p', 'p', 'p', 'd' );
  status   = rtems_task_create(taskName, priority, 8192,
                               (RTEMS_PREEMPT|RTEMS_NO_TIMESLICE|RTEMS_NO_ASR|RTEMS_INTERRUPT_LEVEL(0)),
                               RTEMS_NO_FLOATING_POINT|RTEMS_LOCAL,
                               &rtems_pppd_taskid);
  if ( status == RTEMS_SUCCESSFUL ) {
    status = rtems_task_start(rtems_pppd_taskid, pppTask, 0);
    if ( status == RTEMS_SUCCESSFUL ) {
      iReturn = rtems_pppd_reset_options();
    }
  }

  return ( iReturn );
}

int rtems_pppd_terminate(void)
{
  /* send terminate signal to pppd task */
  rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_29);

  /* call the disconnect function */
  rtems_pppd_disconnect();

  return ( 0 );
}

int rtems_pppd_reset_options(void)
{
    int i;
    struct protent *protp;

    /*
     * Initialize to the standard option set, then parse, in order,
     * the system options file, the user's options file,
     * the tty's options file, and the command line arguments.
     */
    for (i = 0; (protp = protocols[i]) != NULL; ++i)
        (*protp->init)(0);

  return ( 0 );
}

int rtems_pppd_set_hook(int id, rtems_pppd_hookfunction hookfp)
{
  int     iReturn = (int)0;

  switch ( id ) {
  case RTEMS_PPPD_LINKUP_HOOK:
    auth_linkup_hook = hookfp;
    break;
  case RTEMS_PPPD_LINKDOWN_HOOK:
    auth_linkdown_hook = hookfp;
    break;
  case RTEMS_PPPD_IPUP_HOOK:
    ip_up_hook = hookfp;
    break;
  case RTEMS_PPPD_IPDOWN_HOOK:
    ip_down_hook = hookfp;
    break;
  case RTEMS_PPPD_ERROR_HOOK:
    rtems_pppd_errorfp = hookfp;
    break;
  case RTEMS_PPPD_EXIT_HOOK:
    rtems_pppd_exitfp = hookfp;
    break;
  default:
    iReturn = (int)-1;
    break;
  }

  return ( iReturn );
}

int rtems_pppd_set_dialer(rtems_pppd_dialerfunction dialerfp)
{
  pppd_dialer = dialerfp;
  return ( (int)0 );
}

int rtems_pppd_set_option(const char *pOption, const char *pValue)
{
  int                iReturn = (int)0;
  int                prevPhase;
  struct wordlist    option;
  struct wordlist    value;

  if ( pOption != (const char *)0 ) {
    /* initialize the values */
    option.word = (char *)pOption;
    option.next = (struct wordlist *)0;
    if ( pValue != (const char *)0 ) {
      option.next = &value;
      value.word  = (char *)pValue;
      value.next  = (struct wordlist *)0;
    }

    /* save current phase value */
    prevPhase = phase;
    phase     = PHASE_INITIALIZE;

    /* process option and reset phase value */
    iReturn = options_from_list(&option, 1);
    phase   = prevPhase;
  }

  return ( iReturn );
}

int rtems_pppd_connect(void)
{
  /* send connect signal to pppd task */
  rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_30);

  return ( 0 );
}

int rtems_pppd_disconnect(void)
{
  /* set pppd global variables to disconnect */
  persist   = 0;
  kill_link = 1;

  /* send event to wake up the pppd code */
  /* pretend its a serial interrput */
  rtems_event_send(rtems_pppd_taskid, RTEMS_EVENT_31);

  return ( 0 );
}