xref: /netbsd-src/sys/net/if.c (revision cda4f8f6ee55684e8d311b86c99ea59191e6b74f)
1 /*
2  * Copyright (c) 1980, 1986 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  *	from: @(#)if.c	7.14 (Berkeley) 4/20/91
34  *	$Id: if.c,v 1.4 1993/06/27 06:02:26 andrew Exp $
35  */
36 
37 #include "param.h"
38 #include "mbuf.h"
39 #include "systm.h"
40 #include "socket.h"
41 #include "socketvar.h"
42 #include "protosw.h"
43 #include "proc.h"
44 #include "kernel.h"
45 #include "ioctl.h"
46 
47 #include "if.h"
48 #include "af.h"
49 #include "if_dl.h"
50 #include "if_types.h"
51 
52 #include "ether.h"
53 
54 int	ifqmaxlen = IFQ_MAXLEN;
55 
56 void if_slowtimo(caddr_t);
57 
58 /*
59  * Network interface utility routines.
60  *
61  * Routines with ifa_ifwith* names take sockaddr *'s as
62  * parameters.
63  */
64 
65 void
66 ifinit()
67 {
68 	register struct ifnet *ifp;
69 
70 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
71 		if (ifp->if_snd.ifq_maxlen == 0)
72 			ifp->if_snd.ifq_maxlen = ifqmaxlen;
73 	if_slowtimo(NULL);
74 }
75 
76 #ifdef vax
77 /*
78  * Call each interface on a Unibus reset.
79  */
80 ifubareset(uban)
81 	int uban;
82 {
83 	register struct ifnet *ifp;
84 
85 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
86 		if (ifp->if_reset)
87 			(*ifp->if_reset)(ifp->if_unit, uban);
88 }
89 #endif
90 
91 int if_index = 0;
92 struct ifaddr **ifnet_addrs;
93 static char *sprint_d();
94 
95 /*
96  * Attach an interface to the
97  * list of "active" interfaces.
98  */
99 if_attach(ifp)
100 	struct ifnet *ifp;
101 {
102 	unsigned socksize, ifasize;
103 	int namelen, unitlen;
104 	char workbuf[12], *unitname;
105 	register struct ifnet **p = &ifnet;
106 	register struct sockaddr_dl *sdl;
107 	register struct ifaddr *ifa;
108 	static int if_indexlim = 8;
109 	extern link_rtrequest(), ether_output();
110 
111 	while (*p)
112 		p = &((*p)->if_next);
113 	*p = ifp;
114 	ifp->if_index = ++if_index;
115 	if (ifnet_addrs == 0 || if_index >= if_indexlim) {
116 		unsigned n = (if_indexlim <<= 1) * sizeof(ifa);
117 		struct ifaddr **q = (struct ifaddr **)
118 					malloc(n, M_IFADDR, M_WAITOK);
119 		if (ifnet_addrs) {
120 			bcopy((caddr_t)ifnet_addrs, (caddr_t)q, n/2);
121 			free((caddr_t)ifnet_addrs, M_IFADDR);
122 		}
123 		ifnet_addrs = q;
124 	}
125 	/* XXX -- Temporary fix before changing 10 ethernet drivers */
126 	if (ifp->if_output == ether_output) {
127 		ifp->if_type = IFT_ETHER;
128 		ifp->if_addrlen = 6;
129 		ifp->if_hdrlen = 14;
130 	}
131 	/*
132 	 * create a Link Level name for this device
133 	 */
134 	unitname = sprint_d((u_int)ifp->if_unit, workbuf, sizeof(workbuf));
135 	namelen = strlen(ifp->if_name);
136 	unitlen = strlen(unitname);
137 #define _offsetof(t, m) ((int)((caddr_t)&((t *)0)->m))
138 	socksize = _offsetof(struct sockaddr_dl, sdl_data[0]) +
139 			       unitlen + namelen + ifp->if_addrlen;
140 #define ROUNDUP(a) (1 + (((a) - 1) | (sizeof(long) - 1)))
141 	socksize = ROUNDUP(socksize);
142 	if (socksize < sizeof(*sdl))
143 		socksize = sizeof(*sdl);
144 	ifasize = sizeof(*ifa) + 2 * socksize;
145 	ifa = (struct ifaddr *)malloc(ifasize, M_IFADDR, M_WAITOK);
146 	if (ifa == 0)
147 		return;
148 	ifnet_addrs[if_index - 1] = ifa;
149 	bzero((caddr_t)ifa, ifasize);
150 	sdl = (struct sockaddr_dl *)(ifa + 1);
151 	ifa->ifa_addr = (struct sockaddr *)sdl;
152 	ifa->ifa_ifp = ifp;
153 	sdl->sdl_len = socksize;
154 	sdl->sdl_family = AF_LINK;
155 	bcopy(ifp->if_name, sdl->sdl_data, namelen);
156 	bcopy(unitname, namelen + (caddr_t)sdl->sdl_data, unitlen);
157 	sdl->sdl_nlen = (namelen += unitlen);
158 	sdl->sdl_index = ifp->if_index;
159 	sdl = (struct sockaddr_dl *)(socksize + (caddr_t)sdl);
160 	ifa->ifa_netmask = (struct sockaddr *)sdl;
161 	sdl->sdl_len = socksize - ifp->if_addrlen;
162 	while (namelen != 0)
163 		sdl->sdl_data[--namelen] = 0xff;
164 	ifa->ifa_next = ifp->if_addrlist;
165 	ifa->ifa_rtrequest = link_rtrequest;
166 	ifp->if_addrlist = ifa;
167 }
168 /*
169  * Locate an interface based on a complete address.
170  */
171 /*ARGSUSED*/
172 struct ifaddr *
173 ifa_ifwithaddr(addr)
174 	register struct sockaddr *addr;
175 {
176 	register struct ifnet *ifp;
177 	register struct ifaddr *ifa;
178 
179 #define	equal(a1, a2) \
180   (bcmp((caddr_t)(a1), (caddr_t)(a2), ((struct sockaddr *)(a1))->sa_len) == 0)
181 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
182 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
183 		if (ifa->ifa_addr->sa_family != addr->sa_family)
184 			continue;
185 		if (equal(addr, ifa->ifa_addr))
186 			return (ifa);
187 		if ((ifp->if_flags & IFF_BROADCAST) && ifa->ifa_broadaddr &&
188 		    equal(ifa->ifa_broadaddr, addr))
189 			return (ifa);
190 	}
191 	return ((struct ifaddr *)0);
192 }
193 /*
194  * Locate the point to point interface with a given destination address.
195  */
196 /*ARGSUSED*/
197 struct ifaddr *
198 ifa_ifwithdstaddr(addr)
199 	register struct sockaddr *addr;
200 {
201 	register struct ifnet *ifp;
202 	register struct ifaddr *ifa;
203 
204 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
205 	    if (ifp->if_flags & IFF_POINTOPOINT)
206 		for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
207 			if (ifa->ifa_addr->sa_family != addr->sa_family)
208 				continue;
209 			if (equal(addr, ifa->ifa_dstaddr))
210 				return (ifa);
211 	}
212 	return ((struct ifaddr *)0);
213 }
214 
215 /*
216  * Find an interface on a specific network.  If many, choice
217  * is first found.
218  */
219 struct ifaddr *
220 ifa_ifwithnet(addr)
221 	struct sockaddr *addr;
222 {
223 	register struct ifnet *ifp;
224 	register struct ifaddr *ifa;
225 	u_int af = addr->sa_family;
226 
227 	if (af >= AF_MAX)
228 		return (0);
229 	if (af == AF_LINK) {
230 	    register struct sockaddr_dl *sdl = (struct sockaddr_dl *)addr;
231 	    if (sdl->sdl_index && sdl->sdl_index <= if_index)
232 		return (ifnet_addrs[sdl->sdl_index - 1]);
233 	}
234 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
235 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
236 		register char *cp, *cp2, *cp3;
237 		register char *cplim;
238 		if (ifa->ifa_addr->sa_family != af || ifa->ifa_netmask == 0)
239 			continue;
240 		cp = addr->sa_data;
241 		cp2 = ifa->ifa_addr->sa_data;
242 		cp3 = ifa->ifa_netmask->sa_data;
243 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
244 		for (; cp3 < cplim; cp3++)
245 			if ((*cp++ ^ *cp2++) & *cp3)
246 				break;
247 		if (cp3 == cplim)
248 			return (ifa);
249 	    }
250 	return ((struct ifaddr *)0);
251 }
252 
253 /*
254  * Find an interface using a specific address family
255  */
256 struct ifaddr *
257 ifa_ifwithaf(af)
258 	register int af;
259 {
260 	register struct ifnet *ifp;
261 	register struct ifaddr *ifa;
262 
263 	for (ifp = ifnet; ifp; ifp = ifp->if_next)
264 	    for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
265 		if (ifa->ifa_addr->sa_family == af)
266 			return (ifa);
267 	return ((struct ifaddr *)0);
268 }
269 
270 /*
271  * Find an interface address specific to an interface best matching
272  * a given address.
273  */
274 struct ifaddr *
275 ifaof_ifpforaddr(addr, ifp)
276 	struct sockaddr *addr;
277 	register struct ifnet *ifp;
278 {
279 	register struct ifaddr *ifa;
280 	register char *cp, *cp2, *cp3;
281 	register char *cplim;
282 	struct ifaddr *ifa_maybe = 0;
283 	u_int af = addr->sa_family;
284 
285 	if (af >= AF_MAX)
286 		return (0);
287 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next) {
288 		if (ifa->ifa_addr->sa_family != af)
289 			continue;
290 		ifa_maybe = ifa;
291 		if (ifa->ifa_netmask == 0) {
292 			if (equal(addr, ifa->ifa_addr) ||
293 			    (ifa->ifa_dstaddr && equal(addr, ifa->ifa_dstaddr)))
294 				return (ifa);
295 			continue;
296 		}
297 		cp = addr->sa_data;
298 		cp2 = ifa->ifa_addr->sa_data;
299 		cp3 = ifa->ifa_netmask->sa_data;
300 		cplim = ifa->ifa_netmask->sa_len + (char *)ifa->ifa_netmask;
301 		for (; cp3 < cplim; cp3++)
302 			if ((*cp++ ^ *cp2++) & *cp3)
303 				break;
304 		if (cp3 == cplim)
305 			return (ifa);
306 	}
307 	return (ifa_maybe);
308 }
309 #include "route.h"
310 /*
311  * Default action when installing a route with a Link Level gateway.
312  * Lookup an appropriate real ifa to point to.
313  * This should be moved to /sys/net/link.c eventually.
314  */
315 link_rtrequest(cmd, rt, sa)
316 register struct rtentry *rt;
317 struct sockaddr *sa;
318 {
319 	register struct ifaddr *ifa;
320 	struct sockaddr *dst;
321 	struct ifnet *ifp, *oldifnet = ifnet;
322 
323 	if (cmd != RTM_ADD || ((ifa = rt->rt_ifa) == 0) ||
324 	    ((ifp = ifa->ifa_ifp) == 0) || ((dst = rt_key(rt)) == 0))
325 		return;
326 	if (ifa = ifaof_ifpforaddr(dst, ifp)) {
327 		rt->rt_ifa = ifa;
328 		if (ifa->ifa_rtrequest && ifa->ifa_rtrequest != link_rtrequest)
329 			ifa->ifa_rtrequest(cmd, rt, sa);
330 	}
331 }
332 
333 /*
334  * Mark an interface down and notify protocols of
335  * the transition.
336  * NOTE: must be called at splnet or eqivalent.
337  */
338 if_down(ifp)
339 	register struct ifnet *ifp;
340 {
341 	register struct ifaddr *ifa;
342 
343 	ifp->if_flags &= ~IFF_UP;
344 	for (ifa = ifp->if_addrlist; ifa; ifa = ifa->ifa_next)
345 		pfctlinput(PRC_IFDOWN, ifa->ifa_addr);
346 	if_qflush(&ifp->if_snd);
347 }
348 
349 /*
350  * Flush an interface queue.
351  */
352 if_qflush(ifq)
353 	register struct ifqueue *ifq;
354 {
355 	register struct mbuf *m, *n;
356 
357 	n = ifq->ifq_head;
358 	while (m = n) {
359 		n = m->m_act;
360 		m_freem(m);
361 	}
362 	ifq->ifq_head = 0;
363 	ifq->ifq_tail = 0;
364 	ifq->ifq_len = 0;
365 }
366 
367 /*
368  * Handle interface watchdog timer routines.  Called
369  * from softclock, we decrement timers (if set) and
370  * call the appropriate interface routine on expiration.
371  */
372 /* ARGSUSED */
373 void
374 if_slowtimo(caddr_t arg)
375 {
376 	register struct ifnet *ifp;
377 	int s = splimp();
378 
379 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
380 		if (ifp->if_timer == 0 || --ifp->if_timer)
381 			continue;
382 		if (ifp->if_watchdog)
383 			(*ifp->if_watchdog)(ifp->if_unit);
384 	}
385 	splx(s);
386 	timeout(if_slowtimo, (caddr_t)0, hz / IFNET_SLOWHZ);
387 }
388 
389 /*
390  * Map interface name to
391  * interface structure pointer.
392  */
393 struct ifnet *
394 ifunit(name)
395 	register char *name;
396 {
397 	register char *cp;
398 	register struct ifnet *ifp;
399 	int unit;
400 	unsigned len;
401 	char *ep, c;
402 
403 	for (cp = name; cp < name + IFNAMSIZ && *cp; cp++)
404 		if (*cp >= '0' && *cp <= '9')
405 			break;
406 	if (*cp == '\0' || cp == name + IFNAMSIZ)
407 		return ((struct ifnet *)0);
408 	/*
409 	 * Save first char of unit, and pointer to it,
410 	 * so we can put a null there to avoid matching
411 	 * initial substrings of interface names.
412 	 */
413 	len = cp - name + 1;
414 	c = *cp;
415 	ep = cp;
416 	for (unit = 0; *cp >= '0' && *cp <= '9'; )
417 		unit = unit * 10 + *cp++ - '0';
418 	*ep = 0;
419 	for (ifp = ifnet; ifp; ifp = ifp->if_next) {
420 		if (bcmp(ifp->if_name, name, len))
421 			continue;
422 		if (unit == ifp->if_unit)
423 			break;
424 	}
425 	*ep = c;
426 	return (ifp);
427 }
428 
429 /*
430  * Interface ioctls.
431  */
432 ifioctl(so, cmd, data, p)
433 	struct socket *so;
434 	int cmd;
435 	caddr_t data;
436 	struct proc *p;
437 {
438 	register struct ifnet *ifp;
439 	register struct ifreq *ifr;
440 	int error;
441 
442 	switch (cmd) {
443 
444 	case SIOCGIFCONF:
445 	case OSIOCGIFCONF:
446 		return (ifconf(cmd, data));
447 
448 #if defined(INET) && NETHER > 0
449 	case SIOCSARP:
450 	case SIOCDARP:
451 		if (error = suser(p->p_ucred, &p->p_acflag))
452 			return (error);
453 		/* FALL THROUGH */
454 	case SIOCGARP:
455 	case OSIOCGARP:
456 		return (arpioctl(cmd, data));
457 #endif
458 	}
459 	ifr = (struct ifreq *)data;
460 	ifp = ifunit(ifr->ifr_name);
461 	if (ifp == 0)
462 		return (ENXIO);
463 	switch (cmd) {
464 
465 	case SIOCGIFFLAGS:
466 		ifr->ifr_flags = ifp->if_flags;
467 		break;
468 
469 	case SIOCGIFMETRIC:
470 		ifr->ifr_metric = ifp->if_metric;
471 		break;
472 
473 	case SIOCSIFFLAGS:
474 		if (error = suser(p->p_ucred, &p->p_acflag))
475 			return (error);
476 		if (ifp->if_flags & IFF_UP && (ifr->ifr_flags & IFF_UP) == 0) {
477 			int s = splimp();
478 			if_down(ifp);
479 			splx(s);
480 		}
481 		ifp->if_flags = (ifp->if_flags & IFF_CANTCHANGE) |
482 			(ifr->ifr_flags &~ IFF_CANTCHANGE);
483 		if (ifp->if_ioctl)
484 			(void) (*ifp->if_ioctl)(ifp, cmd, data);
485 		break;
486 
487 	case SIOCSIFMETRIC:
488 		if (error = suser(p->p_ucred, &p->p_acflag))
489 			return (error);
490 		ifp->if_metric = ifr->ifr_metric;
491 		break;
492 
493 	default:
494 		if (so->so_proto == 0)
495 			return (EOPNOTSUPP);
496 #ifndef COMPAT_43
497 		return ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
498 			cmd, data, ifp));
499 #else
500 	    {
501 		int ocmd = cmd;
502 
503 		switch (cmd) {
504 
505 		case SIOCSIFDSTADDR:
506 		case SIOCSIFADDR:
507 		case SIOCSIFBRDADDR:
508 		case SIOCSIFNETMASK:
509 #if BYTE_ORDER != BIG_ENDIAN
510 			if (ifr->ifr_addr.sa_family == 0 &&
511 			    ifr->ifr_addr.sa_len < 16) {
512 				ifr->ifr_addr.sa_family = ifr->ifr_addr.sa_len;
513 				ifr->ifr_addr.sa_len = 16;
514 			}
515 #else
516 			if (ifr->ifr_addr.sa_len == 0)
517 				ifr->ifr_addr.sa_len = 16;
518 #endif
519 			break;
520 
521 		case OSIOCGIFADDR:
522 			cmd = SIOCGIFADDR;
523 			break;
524 
525 		case OSIOCGIFDSTADDR:
526 			cmd = SIOCGIFDSTADDR;
527 			break;
528 
529 		case OSIOCGIFBRDADDR:
530 			cmd = SIOCGIFBRDADDR;
531 			break;
532 
533 		case OSIOCGIFNETMASK:
534 			cmd = SIOCGIFNETMASK;
535 		}
536 		error =  ((*so->so_proto->pr_usrreq)(so, PRU_CONTROL,
537 							    cmd, data, ifp));
538 		switch (ocmd) {
539 
540 		case OSIOCGIFADDR:
541 		case OSIOCGIFDSTADDR:
542 		case OSIOCGIFBRDADDR:
543 		case OSIOCGIFNETMASK:
544 			*(u_short *)&ifr->ifr_addr = ifr->ifr_addr.sa_family;
545 		}
546 		return (error);
547 
548 	    }
549 #endif
550 	}
551 	return (0);
552 }
553 
554 /*
555  * Return interface configuration
556  * of system.  List may be used
557  * in later ioctl's (above) to get
558  * other information.
559  */
560 /*ARGSUSED*/
561 ifconf(cmd, data)
562 	int cmd;
563 	caddr_t data;
564 {
565 	register struct ifconf *ifc = (struct ifconf *)data;
566 	register struct ifnet *ifp = ifnet;
567 	register struct ifaddr *ifa;
568 	register char *cp, *ep;
569 	struct ifreq ifr, *ifrp;
570 	int space = ifc->ifc_len, error = 0;
571 
572 	ifrp = ifc->ifc_req;
573 	ep = ifr.ifr_name + sizeof (ifr.ifr_name) - 2;
574 	for (; space > sizeof (ifr) && ifp; ifp = ifp->if_next) {
575 		bcopy(ifp->if_name, ifr.ifr_name, sizeof (ifr.ifr_name) - 2);
576 		for (cp = ifr.ifr_name; cp < ep && *cp; cp++)
577 			;
578 		*cp++ = '0' + ifp->if_unit; *cp = '\0';
579 		if ((ifa = ifp->if_addrlist) == 0) {
580 			bzero((caddr_t)&ifr.ifr_addr, sizeof(ifr.ifr_addr));
581 			error = copyout((caddr_t)&ifr, (caddr_t)ifrp, sizeof (ifr));
582 			if (error)
583 				break;
584 			space -= sizeof (ifr), ifrp++;
585 		} else
586 		    for ( ; space > sizeof (ifr) && ifa; ifa = ifa->ifa_next) {
587 			register struct sockaddr *sa = ifa->ifa_addr;
588 #ifdef COMPAT_43
589 			if (cmd == OSIOCGIFCONF) {
590 				struct osockaddr *osa =
591 					 (struct osockaddr *)&ifr.ifr_addr;
592 				ifr.ifr_addr = *sa;
593 				osa->sa_family = sa->sa_family;
594 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
595 						sizeof (ifr));
596 				ifrp++;
597 			} else
598 #endif
599 			if (sa->sa_len <= sizeof(*sa)) {
600 				ifr.ifr_addr = *sa;
601 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
602 						sizeof (ifr));
603 				ifrp++;
604 			} else {
605 				space -= sa->sa_len - sizeof(*sa);
606 				if (space < sizeof (ifr))
607 					break;
608 				error = copyout((caddr_t)&ifr, (caddr_t)ifrp,
609 						sizeof (ifr.ifr_name));
610 				if (error == 0)
611 				    error = copyout((caddr_t)sa,
612 				      (caddr_t)&ifrp->ifr_addr, sa->sa_len);
613 				ifrp = (struct ifreq *)
614 					(sa->sa_len + (caddr_t)&ifrp->ifr_addr);
615 			}
616 			if (error)
617 				break;
618 			space -= sizeof (ifr);
619 		}
620 	}
621 	ifc->ifc_len -= space;
622 	return (error);
623 }
624 
625 static char *
626 sprint_d(n, buf, buflen)
627 	u_int n;
628 	char *buf;
629 	int buflen;
630 {
631 	register char *cp = buf + buflen - 1;
632 
633 	*cp = 0;
634 	do {
635 		cp--;
636 		*cp = "0123456789"[n % 10];
637 		n /= 10;
638 	} while (n != 0);
639 	return (cp);
640 }
641